GitLab Self-Managed 是集代码仓库、Merge Request、CI/CD、Package Registry、Container Registry、Issue、Wiki 和安全能力于一体的 DevSecOps 平台。企业部署 GitLab 后,通常希望复用现有 LDAP 目录和 CAS 单点登录,而不是再维护一套独立账号。
推荐身份架构:
1 2 3 OpenLDAP:保存用户、组织、用户组和账号状态 Apereo CAS:使用 LDAP 验证用户,并作为 SAML 2.0 IdP 提供 SSO GitLab:通过 LDAP 同步/认证用户,通过 SAML 接入 CAS 单点登录
这里有一个关键事实:
GitLab 过去使用 omniauth-cas3 直接支持 CAS,但该 Provider 已在 GitLab 16.0 移除。现代 GitLab 不应再配置直接 CAS OmniAuth,而应让 CAS 暴露 SAML 2.0 或 OIDC,再使用 GitLab 官方支持的 SAML/OIDC 集成。
本文使用:
1 2 3 4 GitLab Self-Managed 18.x OpenLDAP LDAPS Apereo CAS 7.3.x SAML IdP Rocky Linux 10
一、整体架构
组件
地址
说明
GitLab
https://gitlab.example.com
GitLab Self-Managed
OpenLDAP
ldaps://ldap.example.com:636
用户目录
CAS
https://sso.example.com/cas
认证中心与 SAML IdP
GitLab Server
192.168.9.30
Rocky Linux 10
LDAP Base DN
dc=example,dc=com
目录根节点
sequenceDiagram
participant U as 用户浏览器
participant G as GitLab
participant C as CAS SAML IdP
participant L as OpenLDAP
U->>G: 访问 GitLab
G-->>U: 跳转 CAS SAML IdP
U->>C: 登录
C->>L: LDAP Bind 验证
L-->>C: 认证成功并返回属性
C-->>U: 返回 SAML Response
U->>G: POST SAML Assertion
G->>G: 按 NameID/邮箱关联 LDAP 用户
G-->>U: 建立 GitLab 会话
用户生命周期:
1 2 3 4 LDAP 创建/禁用用户 -> GitLab LDAP 同步或登录创建用户 -> CAS 通过 SAML 登录并关联同一 GitLab 用户 -> GitLab 组和项目决定权限
二、资源规划 2.1 资源建议
用户/规模
CPU
内存
数据盘
测试
4 核
8 GB
100 GB SSD
小型团队
8 核
16 GB
500 GB SSD
中型团队
16 核
32 GB
1 TB 以上 SSD
大型环境
按官方 Reference Architecture
64 GB 以上
独立存储与多节点
GitLab 资源主要消耗于:
Puma/Rails;
Sidekiq;
Gitaly Git 操作;
PostgreSQL;
Redis;
Repository、LFS、Artifacts、Packages;
Container Registry;
CI/CD 并发和日志;
备份与仓库打包。
2.2 端口
端口
用途
22
Git SSH,建议与宿主机 SSH 区分
80
HTTP 跳转 HTTPS
443
GitLab Web、Git HTTPS、SAML 回调
636 出站
LDAP
443 出站
CAS SAML IdP
5050 可选
GitLab Container Registry 独立端口
三、Rocky Linux 10 初始化 1 2 3 4 cat /etc/rocky-releaseuname -runame -m hostnamectl
1 2 3 4 hostnamectl set-hostname gitlab01.example.com timedatectl set-timezone Asia/Shanghai systemctl enable --now chronyd chronyc tracking
1 2 3 4 5 6 7 8 dnf clean all dnf makecache dnf upgrade -y dnf install -y \ curl openssh-server openssh-clients \ policycoreutils-python-utils postfix \ firewalld vim jq bind-utils lsof
启动 SSH、Postfix 和防火墙:
1 2 3 systemctl enable --now sshd systemctl enable --now postfix systemctl enable --now firewalld
生产环境可将邮件改为企业 SMTP,而不是依赖本机 Postfix 直接投递。
四、安装 GitLab Linux Package 4.1 添加官方仓库 下载并检查仓库脚本:
1 2 3 4 5 6 curl --location \ "https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.rpm.sh" \ --output /tmp/gitlab-repo.sh less /tmp/gitlab-repo.shsudo bash /tmp/gitlab-repo.sh
查看可用版本:
1 2 3 dnf list gitlab-ee --showduplicates \ | sort -Vr \ | head -20
生产环境应固定经过测试的 GitLab 18.x Patch 版本。GitLab EE 包在没有付费许可证时也可使用 Free Tier 能力;也可以安装 gitlab-ce。
4.2 安装 1 2 sudo EXTERNAL_URL="https://gitlab.example.com" \ dnf install -y gitlab-ee
安装完成后主要目录:
路径
用途
/etc/gitlab/gitlab.rb
主配置
/etc/gitlab/gitlab-secrets.json
加密密钥
/var/opt/gitlab
数据目录
/var/log/gitlab
日志
/opt/gitlab
程序文件
检查:
1 2 gitlab-ctl status gitlab-rake gitlab:env :info
初始 Root 密码:
1 cat /etc/gitlab/initial_root_password
该文件会自动过期清理。首次登录后立即修改密码并创建日常管理员。
五、配置 HTTPS 5.1 使用外部证书 1 2 mkdir -p /etc/gitlab/sslchmod 0755 /etc/gitlab/ssl
1 2 3 4 5 6 7 install -o root -g root -m 0644 \ gitlab.example.com.fullchain.crt \ /etc/gitlab/ssl/gitlab.example.com.crt install -o root -g root -m 0600 \ gitlab.example.com.key \ /etc/gitlab/ssl/gitlab.example.com.key
编辑 /etc/gitlab/gitlab.rb:
1 2 3 4 5 6 7 8 9 external_url 'https://gitlab.example.com' nginx['redirect_http_to_https' ] = true nginx['ssl_certificate' ] = '/etc/gitlab/ssl/gitlab.example.com.crt' nginx['ssl_certificate_key' ] = '/etc/gitlab/ssl/gitlab.example.com.key' nginx['ssl_protocols' ] = 'TLSv1.2 TLSv1.3' nginx['hsts_max_age' ] = 31536000 nginx['hsts_include_subdomains' ] = false
应用:
1 2 gitlab-ctl reconfigure gitlab-ctl restart
验证:
1 2 3 curl -I https://gitlab.example.com/users/sign_in gitlab-rake gitlab:check SANITIZE=true
5.2 防火墙 1 2 3 firewall-cmd --permanent --add-service=http firewall-cmd --permanent --add-service=https firewall-cmd --reload
Git SSH 如果使用 22,需要确保宿主机 SSH 不与 GitLab 冲突。推荐:
1 2 宿主机 SSH:2222,仅管理网 GitLab SSH:22
或者:
1 2 宿主机 SSH:22 GitLab SSH:2222
GitLab SSH 端口配置:
1 gitlab_rails['gitlab_shell_ssh_port' ] = 2222
六、准备 LDAP LDAP 目录:
1 2 3 4 5 6 7 8 dc=example,dc=com ├── ou=people ├── ou=groups │ ├── cn=gitlab-users │ ├── cn=gitlab-admins │ └── cn=gitlab-developers └── ou=system └── cn=gitlab-reader
专用 Reader:
1 cn=gitlab-reader,ou=system,dc=example,dc=com
Reader 只需搜索用户和组,不允许修改用户或读取 userPassword。
测试:
1 2 3 4 5 6 7 8 ldapsearch \ -x -LLL \ -H ldaps://ldap.example.com:636 \ -D 'cn=gitlab-reader,ou=system,dc=example,dc=com' \ -W \ -b 'ou=people,dc=example,dc=com' \ '(&(objectClass=inetOrgPerson)(uid=alice))' \ uid cn mail memberOf
七、配置 GitLab 信任 LDAP CA 复制 CA 到 GitLab 信任目录:
1 2 3 4 5 mkdir -p /etc/gitlab/trusted-certs install -o root -g root -m 0644 \ company-root-ca.crt \ /etc/gitlab/trusted-certs/company-root-ca.crt
GitLab Reconfigure 会更新内部信任链。
验证:
1 2 3 4 5 openssl s_client \ -connect ldap.example.com:636 \ -servername ldap.example.com \ -CAfile /etc/gitlab/trusted-certs/company-root-ca.crt \ -verify_return_error
不要配置 verify_certificates: false 长期绕过证书错误。
八、GitLab 集成 LDAP 编辑 /etc/gitlab/gitlab.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 gitlab_rails['ldap_enabled' ] = true gitlab_rails['ldap_servers' ] = { 'main' => { 'label' => 'Company LDAP' , 'host' => 'ldap.example.com' , 'port' => 636 , 'uid' => 'uid' , 'bind_dn' => 'cn=gitlab-reader,ou=system,dc=example,dc=com' , 'password' => '替换为LDAP Reader密码' , 'encryption' => 'simple_tls' , 'verify_certificates' => true , 'timeout' => 10 , 'active_directory' => false , 'allow_username_or_email_login' => false , 'lowercase_usernames' => true , 'block_auto_created_users' => false , 'base' => 'ou=people,dc=example,dc=com' , 'user_filter' => '(&(objectClass=inetOrgPerson)(memberOf=cn=gitlab-users,ou=groups,dc=example,dc=com))' , 'attributes' => { 'username' => ['uid' ], 'email' => ['mail' ], 'name' => ['cn' ], 'first_name' => ['givenName' ], 'last_name' => ['sn' ] } } }
保护配置:
1 2 chown root:root /etc/gitlab/gitlab.rbchmod 0600 /etc/gitlab/gitlab.rb
gitlab.rb 是 Ruby 代码,并由 Root 执行 reconfigure,不能让普通用户写入。
应用:
检查 LDAP:
1 gitlab-rake gitlab:ldap:check
输出会显示:
LDAP 连接状态;
用户样例;
用户名和邮箱;
是否能够搜索。
8.1 LDAP 登录策略 推荐:
1 2 3 4 uid:不可变用户名 mail:用户邮箱 cn:显示名称 memberOf:用户组过滤
不要允许邮箱和用户名混合登录,除非目录对两者唯一性有严格保证。
8.2 LDAP 用户禁用 GitLab 会根据 LDAP 身份状态阻止或解除阻止用户,但具体同步行为取决于版本和登录/同步任务。上线前必须测试:
LDAP 用户正常;
用户从 gitlab-users 移除;
运行同步或重新登录;
GitLab 用户被阻止;
恢复组成员;
用户恢复访问。
8.3 LDAP 组同步 更高级的 LDAP Group Sync、角色映射等能力可能受 GitLab Tier 影响。基础 Free 环境可以:
用 user_filter 控制是否允许登录;
在 GitLab 中管理 Group/Project Membership;
通过 API 自动同步 LDAP 组到 GitLab 组;
升级到支持原生 Group Sync 的 Tier。
九、为什么不直接配置 CAS Provider 旧文章可能存在:
或者:
该 Provider 已在 GitLab 16.0 移除。现代 GitLab 继续复制这些配置会出现:
Provider 不存在;
Bundle 缺少 Gem;
Reconfigure 后登录按钮不出现;
升级不可支持;
自行修改 GitLab Bundle 导致后续升级失败。
正确路线:
1 2 3 CAS 使用 LDAP 认证 CAS 开启 SAML 2.0 IdP GitLab 使用官方 SAML OmniAuth
十、为 CAS 增加 SAML IdP 能力 在 CAS Overlay 的 build.gradle 中增加与当前 CAS 版本匹配的 SAML IdP 模块:
1 2 3 dependencies { implementation "org.apereo.cas:cas-server-support-saml-idp" }
重新构建并部署 CAS:
1 ./gradlew clean build -x test --no-daemon
CAS SAML IdP 通常需要:
IdP Entity ID;
签名证书和私钥;
SAML Metadata 存储;
SP Registered Service;
属性释放策略;
NameID 策略。
示例配置方向:
1 2 cas.authn.saml-idp.core.entity-id =https://sso.example.com/cas/idp cas.authn.saml-idp.metadata.file-system.location =file:/etc/cas/saml
SAML IdP 属性必须来源于 LDAP:
CAS 7.3.x 的具体属性名和模块配置可能随 Patch 调整,应使用当前 CAS 文档和启动日志核对。
十一、在 CAS 注册 GitLab SAML SP GitLab SP Metadata:
1 https://gitlab.example.com/users/auth/saml/metadata
GitLab ACS:
1 https://gitlab.example.com/users/auth/saml/callback
GitLab Entity ID:
1 https://gitlab.example.com
CAS SamlRegisteredService 示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 { "@class" : "org.apereo.cas.support.saml.services.SamlRegisteredService" , "serviceId" : "https://gitlab.example.com" , "name" : "GitLab" , "id" : 30000001 , "evaluationOrder" : 10 , "metadataLocation" : "https://gitlab.example.com/users/auth/saml/metadata" , "attributeReleasePolicy" : { "@class" : "org.apereo.cas.services.ReturnAllowedAttributeReleasePolicy" , "allowedAttributes" : [ "uid" , "mail" , "cn" , "memberOf" ] } }
类名和 JSON 结构必须以当前 CAS 版本为准。
NameID 推荐使用:
1 稳定且不可变的 employeeId 或 uid
不要使用用户可自行修改的属性作为 NameID。
十二、GitLab 配置 SAML 先获取 CAS IdP 签名证书 SHA-1 Fingerprint。GitLab 当前示例仍支持 Fingerprint 配置,也可按官方文档使用更完整的证书方式。
1 2 3 4 5 openssl x509 \ -in cas-saml-signing.crt \ -noout \ -fingerprint \ -sha1
编辑 /etc/gitlab/gitlab.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 gitlab_rails['omniauth_enabled' ] = true gitlab_rails['omniauth_allow_single_sign_on' ] = ['saml' ] gitlab_rails['omniauth_block_auto_created_users' ] = false gitlab_rails['omniauth_auto_link_saml_user' ] = true gitlab_rails['omniauth_providers' ] = [ { name: 'saml' , label: 'CAS SSO' , args: { assertion_consumer_service_url: 'https://gitlab.example.com/users/auth/saml/callback' , idp_cert_fingerprint: 'AA:BB:CC:DD:EE:FF:替换为真实指纹' , idp_sso_target_url: 'https://sso.example.com/cas/idp/profile/SAML2/Redirect/SSO' , issuer: 'https://gitlab.example.com' , name_identifier_format: 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent' , attribute_statements: { username: ['uid' ], email: ['mail' ], name: ['cn' ], first_name: ['givenName' ], last_name: ['sn' ] } } } ]
应用:
1 2 gitlab-ctl reconfigure gitlab-ctl restart
查看日志:
1 gitlab-ctl tail gitlab-rails
十三、LDAP 用户与 SAML 用户自动关联 理想流程:
1 2 3 4 5 用户先通过 LDAP 登录 GitLab 或被 LDAP 同步创建 -> GitLab 用户邮箱为 alice@example.com -> CAS SAML Assertion 返回同一 mail -> GitLab 自动关联 SAML Identity -> 后续使用 CAS SSO 登录同一个用户
13.1 自动关联的安全条件 只有同时满足以下条件才开启:
1 gitlab_rails['omniauth_auto_link_saml_user' ] = true
条件:
LDAP 邮箱唯一;
CAS mail 来源于 LDAP;
用户不能任意修改 IdP 邮箱;
GitLab 现有用户邮箱已核对;
未允许公共注册制造同邮箱账号;
NameID 稳定不可变。
如果不能保证,关闭自动关联,由管理员或用户在受控流程中绑定。
13.2 防止重复用户 统一:
1 2 3 4 LDAP uid CAS uid SAML NameID GitLab username
如果 NameID 用随机值,而 LDAP 用户用 uid,GitLab 可能建立新身份或新用户。
十四、登录测试 访问:
1 https://gitlab.example.com/users/sign_in
应看到:
1 2 3 LDAP CAS SSO 标准 GitLab 登录(保留应急管理员)
测试:
LDAP 用户名密码登录;
CAS SSO 登录;
检查是否进入同一 GitLab User ID;
检查项目和组权限;
禁用 LDAP 用户;
清理 CAS 会话后重试;
验证 Break-Glass Root。
查看用户 Identity:
1 Admin -> Overview -> Users -> 用户 -> Identities
十五、权限模型 LDAP/CAS 只处理身份,不决定项目权限。
GitLab 权限仍由:
1 2 3 4 5 6 7 8 9 Instance Admin Group Owner Maintainer Developer Reporter Guest/Planner 项目和组成员关系 Protected Branch/Tag Approval Rules
控制。
推荐:
LDAP gitlab-users 只控制是否能登录;
LDAP gitlab-admins 不直接自动变成 Instance Admin,除非有严格审批;
项目权限由 GitLab Group 管理;
CI 服务账号使用 Project/Group Access Token;
不让人员共享 Personal Access Token。
十六、安全加固 16.1 关闭公共注册 1 gitlab_rails['gitlab_signup_enabled' ] = false
16.2 保留本地 Root
强密码;
MFA;
密码库托管;
仅应急使用;
定期测试;
不强制走 CAS。
16.3 Token
设置 PAT 过期;
CI 使用 Project/Group Token;
Runner 使用 Runner Authentication Token;
不把 Token 写入仓库;
定期轮换;
审计异常 Token 使用。
16.4 SSH
禁用密码 SSH;
限制 Root SSH;
只允许现代 Key;
定期清理用户 SSH Key;
配置 Host Key 备份。
16.5 SAML
Assertion 必须签名;
校验证书;
限制 ACS 和 Audience;
NameID 不可变;
CAS 只向 GitLab 释放必要属性;
系统时间必须同步。
十七、性能调优 17.1 数据盘 1 2 3 df -hT /var/opt/gitlabdf -ih /var/opt/gitlabdu -sh /var/opt/gitlab/git-data
推荐:
SSD/NVMe;
Git Data 与系统盘分离;
LFS、Artifacts、Registry 独立容量治理;
保留 20% 以上空间;
监控 inode 和 I/O 延迟。
17.2 LDAP
精确 user_filter;
为 uid、mail、memberOf 建索引;
使用 LDAPS;
设置合理 Timeout;
不使用过宽 Base DN;
监控 LDAP 延迟。
17.3 GitLab 使用官方内置工具:
1 2 3 gitlab-rake gitlab:env :info gitlab-rake gitlab:check SANITIZE=true gitlab-rake gitlab:doctor:secrets
监控 Puma、Sidekiq、PostgreSQL、Redis、Gitaly、Workhorse 和磁盘。
不要凭感觉无限增加 Puma Worker。GitLab 调优应以官方 Reference Architecture 和实际并发为依据。
十八、备份 GitLab Linux Package 官方备份:
默认备份目录:
必须额外备份:
1 2 3 4 5 6 /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json /etc/gitlab/ssl /etc/gitlab/trusted-certs SSH Host Keys CAS SAML 配置和证书
1 2 3 tar --xattrs --acls \ -czf "/backup/gitlab-config-$(date +%F-%H%M%S) .tar.gz" \ /etc/gitlab
gitlab-secrets.json 丢失会导致加密数据无法解密,优先级极高。
18.1 恢复演练 备份不是完成,恢复成功才算完成。至少验证:
Repository;
LFS;
Artifacts;
用户;
LDAP Identity;
SAML Identity;
CI/CD;
SSH;
Registry。
十九、升级 GitLab 升级必须按官方 Upgrade Path,不可随意跨越 Required Stop。
升级前:
1 2 3 gitlab-backup create gitlab-rake gitlab:check SANITIZE=true gitlab-ctl status
查看版本:
1 2 cat /opt/gitlab/version-manifest.txt | head gitlab-rake gitlab:env :info
固定版本升级:
1 2 dnf list gitlab-ee --showduplicates | sort -Vrsudo dnf install gitlab-ee-目标版本
升级后:
1 2 3 gitlab-ctl reconfigure gitlab-rake gitlab:check SANITIZE=true gitlab-rake gitlab:ldap:check
验证 LDAP、SAML、Git、SSH 和 Runner。
二十、常见故障 20.1 LDAP Check 失败 1 2 3 gitlab-rake gitlab:ldap:check gitlab-ctl tail gitlab-rails
检查:
DNS;
636;
CA;
Bind DN;
密码;
Base DN;
Filter;
SELinux/防火墙;
LDAP 索引。
20.2 LDAP 登录创建了错误用户名 检查:
1 2 3 'uid' => 'uid' 'lowercase_usernames' => true 'allow_username_or_email_login' => false
用户名必须与 CAS SAML 返回的 uid 一致。
20.3 SAML 按钮不出现 1 2 gitlab-ctl reconfigure gitlab-ctl tail gitlab-rails
检查:
1 2 gitlab_rails['omniauth_enabled' ] = true gitlab_rails['omniauth_providers' ]
检查 Ruby 语法和 Provider 名称。
20.4 SAML Response 无法验证 检查:
Fingerprint;
CAS 签名证书;
Assertion 是否签名;
Audience;
Recipient;
ACS;
Entity ID;
时间同步;
NameID Format。
20.5 SAML 创建重复用户 关闭:
1 gitlab_rails['omniauth_auto_link_saml_user' ] = false
核对:
1 2 3 4 5 LDAP mail CAS mail GitLab primary email NameID uid
不要直接删除其中一个用户,先迁移仓库、Issue、MR、Token 和成员关系。
20.6 CAS 认证成功但 GitLab 拒绝登录 CAS 只完成身份认证。GitLab 仍可能因为:
用户被 Block;
SAML Identity 未关联;
Required Group 不匹配;
邮箱不一致;
用户未获批准;
SAML 属性缺失;
Sign-up 禁用且未允许自动创建;
而拒绝登录。
1 2 gitlab-ctl reconfigure gitlab-ctl tail
先检查 /etc/gitlab/gitlab.rb Ruby 语法,不要反复重启所有组件碰运气。
二十一、生产检查清单
二十二、总结 现代 GitLab 与 LDAP/CAS 的推荐链路:
1 2 3 OpenLDAP:身份主数据 CAS:LDAP 认证 + SAML IdP GitLab:LDAP 用户目录 + SAML SP
核心原则:
不再使用已移除的 GitLab CAS3 Provider;
CAS 通过 SAML/OIDC 与 GitLab 集成;
LDAP uid、CAS NameID 和 GitLab Username 必须统一;
自动关联只在邮箱和 NameID 可信时开启;
SSO 只解决认证,项目权限仍由 GitLab 管理;
保留本地应急管理员;
LDAP、SAML 和 GitLab 配置必须一同进入备份与升级测试。
把 LDAP 和 CAS 接入 GitLab,不是多放两个登录按钮,而是把用户生命周期、认证会话和代码权限真正串成一条可回收、可审计的链路。
参考资料