为 Linux 软件包安装配置 SSL

Linux 包支持 SSL 配置的几种常见用例。

默认情况下,HTTPS 未启用。要启用 HTTPS,您可以:

  • 使用 Let’s Encrypt 免费的自动 HTTPS。
  • 使用您自己的证书手动配置 HTTPS。
note 如果您使用代理、负载均衡器或其他一些外部设备,来终止极狐GitLab 主机名的 SSL,请参阅外部、代理和负载均衡器 SSL 终止

下表显示了每个极狐GitLab 服务支持的方法。

服务 手动 SSL Let’s Encrypt
极狐GitLab 实例域名
容器镜像仓库
Mattermost
极狐GitLab Pages No

OpenSSL 3 升级

17.7 开始,极狐GitLab 开始使用 OpenSSL 3。有些旧版的 TLS 协议和密钥套件,或者针对外部集成的弱 TLS 证书可能会和默认的 OpenSSL 3 不兼容。

在升级到极狐GitLab 17.7 之前,请使用 OpenSSL 3 指南来识别及获取您的外部集成兼容性信息。

启用 Let’s Encrypt 集成

如果 external_url 设置为 HTTPS 协议且未配置其他证书,则默认启用 Let’s Encrypt

先决条件:

  • 运行验证检查的公共 Let’s Encrypt 服务器必须可以访问端口 80443。验证不适用于非标准端口。如果环境是私有的或隔离的,certbot(Let’s Encrypt 使用的工具)提供了安装 Let’s Encrypt 证书的手动方法

要启用 Let’s Encrypt:

  1. 编辑/etc/gitlab/gitlab.rb并添加或更改以下条目:

    ## GitLab instance
    external_url "https://gitlab.example.com"         # Must use https protocol
    letsencrypt['contact_emails'] = ['foo@email.com'] # Optional
    
    ## Container Registry (optional), must use https protocol
    registry_external_url "https://registry.example.com"
    #registry_nginx['ssl_certificate'] = "path/to/cert"      # Must be absent or commented out
    
    ## Mattermost (optional), must use https protocol
    mattermost_external_url "https://mattermost.example.com"
    
    • 证书每 90 天到期一次。当到期日期临近时,您为 contact_emails 指定的电子邮件地址会收到警报。
    • 极狐GitLab 实例是证书上的主域名。Container Registry 等其他服务作为备用域名添加到同一个证书中。在上面的示例中,主域名是 gitlab.example.com,Container Registry 域名是 registry.example.com。您不需要设置通配符证书。
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

如果 Let’s Encrypt 无法颁发证书,请参阅故障排除部分以获取可能的解决方案。

自动更新证书

默认安装会在每月第 4 天的午夜后安排更新。 在哪一分钟更新由 external_url 中的值确定,帮助在上游 Let’s Encrypt 服务器上分配负载。

要明确设置更新时间:

  1. 编辑 /etc/gitlab/gitlab.rb

    # Renew every 7th day of the month at 12:30
    letsencrypt['auto_renew_hour'] = "12"
    letsencrypt['auto_renew_minute'] = "30"
    letsencrypt['auto_renew_day_of_month'] = "*/7"
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
note 仅当证书在 30 天内到期时才会更新。例如,如果您将其设置为每月 1 日 00:00 更新,并且证书在 31 日到期,则证书将在更新之前到期。

自动更新是由 go-crond 来管理的。您可以通过编辑 /etc/gitlab/gitlab.rb 来给 go-crond 传递命令行参数:

crond['flags'] = {
  'log.json' = true,
  'server.bind' = ':8040'
}

要禁用自动更新:

  1. 编辑 /etc/gitlab/gitlab.rb

    letsencrypt['auto_renew'] = false
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

手动更新证书

使用以下任一命令手动更新 Let’s Encrypt 证书:

sudo gitlab-ctl reconfigure
sudo gitlab-ctl renew-le-certs

仅当证书即将到期时,前面的命令才会生成更新。 如果在更新期间遇到错误,考虑上行速率限制

使用 Let’s Encrypt 以外的 ACME 服务器

您可以使用 Let’s Encrypt 以外的 ACME 服务器,并将极狐GitLab 配置为使用它来获取证书。提供自己的 ACME 服务器的服务有:

要将极狐GitLab 配置为使用自定义 ACME 服务器:

  1. 编辑 /etc/gitlab/gitlab.rb 并设置 ACME 端点:

    external_url 'https://example.com'
    letsencrypt['acme_staging_endpoint'] = 'https://ca.internal/acme/acme/directory'
    letsencrypt['acme_production_endpoint'] = 'https://ca.internal/acme/acme/directory'
    

    如果自定义 ACME 服务器提供了它,那么也可以使用暂存端点。在将请求提交给 ACME 生产之前,首先检查暂存端点确保 ACME 配置正确。这样做是为了在处理配置时避免 ACME 速率限制。

    默认值:

    https://acme-staging-v02.api.letsencrypt.org/directory
    https://acme-v02.api.letsencrypt.org/directory
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

向证书添加备用域

您可以将备用域(或主备用名称)添加到 Let’s Encrypt 证书中。 如果您想使用捆绑的 NGINX 作为其他后端应用程序的反向代理,这会很有用。

备用域的 DNS 记录必须指向极狐GitLab 实例。

要将备用域添加到 Let’s Encrypt 证书中:

  1. 编辑 /etc/gitlab/gitlab.rb 并添加备用域:

     # Separate multiple domains with commas
     letsencrypt['alt_names'] = ['another-application.example.com']
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

为主要的极狐GitLab 应用程序生成的 Let’s Encrypt 证书将包括指定的备用域。生成的文件位于:

  • 对于密钥:/etc/gitlab/ssl/gitlab.example.com.key
  • 对于证书:/etc/gitlab/ssl/gitlab.example.com.crt

手动配置 HTTPS

caution NGINX 配置告诉浏览器和客户端在接下来的 365 天内使用 HSTS,仅通过安全连接与您的极狐GitLab 实例通信。 有关更多配置选项,请参阅配置 HTTP 严格传输安全性。如果启用 HTTPS,您必须至少在接下来的 24 个月内为您的实例提供安全连接。

要启用 HTTPS:

  1. 编辑 /etc/gitlab/gitlab.rb
    1. external_url 设置为您的域名。请注意 URL 中的 https

      external_url "https://gitlab.example.com"
      
    2. 禁用 Let’s Encrypt 集成:

      letsencrypt['enable'] = false
      

      极狐GitLab 尝试在每次重新配置时更新任何 Let’s Encrypt 证书。如果您打算使用自己手动创建的证书,则必须禁用 Let’s Encrypt 集成,否则证书可能会由于自动更新而被覆盖。

  2. 创建 /etc/gitlab/ssl 目录并在那里复制您的密钥和证书:

    sudo mkdir -p /etc/gitlab/ssl
    sudo chmod 755 /etc/gitlab/ssl
    sudo cp gitlab.example.com.key gitlab.example.com.crt /etc/gitlab/ssl/
    

    在示例中,主机名是 gitlab.example.com,因此 Linux 软件包安装会查找私钥和公共证书文件,分别名为 /etc/gitlab/ssl/gitlab.example.com.key/etc/gitlab/ssl/gitlab.example.com.crt。如果需要,您可以使用不同的位置和证书名称

    您必须以正确的顺序使用完整的证书链,以防止客户端连接时出现 SSL 错误:首先是服务器证书,然后是所有中间证书,最后是根 CA。

  3. 可选。如果 certificate.key 文件受密码保护,当您重新配置极狐GitLab 时,NGINX 不会要求输入密码。在这种情况下,Linux 软件包安装会静默失败,没有错误消息。

    要指定密钥文件的密码,请将密码存储在文本文件中(例如,/etc/gitlab/ssl/key_file_password.txt),并将以下内容添加到/etc/gitlab/gitlab.rb

    nginx['ssl_password_file'] = '/etc/gitlab/ssl/key_file_password.txt'
    
  4. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
  5. 可选。如果您使用防火墙,则可能必须打开端口 443 以允许入站 HTTPS 流量:

    # UFW example (Debian, Ubuntu)
    sudo ufw allow https
    
    # lokkit example (RedHat, CentOS 6)
    sudo lokkit -s https
    
    # firewall-cmd (RedHat, Centos 7)
    sudo firewall-cmd --permanent --add-service=https
    sudo systemctl reload firewalld
    

如果您要更新现有证书,请遵循不同的流程

HTTP 请求重定向到 HTTPS

默认情况下,当您指定以 https 开头的 external_url 时,NGINX 不再侦听端口 80 上未加密的 HTTP 流量。要将所有 HTTP 流量重定向到 HTTPS:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['redirect_http_to_https'] = true
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
note 使用 Let’s Encrypt 集成时默认启用此行为。

更改默认 HTTPS 端口

如果您需要使用默认端口 (443) 以外的 HTTPS 端口,请将其指定为 external_url 的一部分:

  1. 编辑 /etc/gitlab/gitlab.rb

    external_url "https://gitlab.example.com:2443"
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

更改默认 SSL 证书位置

如果您的主机名是 gitlab.example.com,Linux 软件包会查找名为 /etc/gitlab/ssl/gitlab.example.com.key 的私钥和默认名为 /etc/gitlab/ssl/gitlab.example.com.crt 的公共证书。

要设置 SSL 证书的不同位置:

  1. 创建一个目录,给它适当的权限,并将.crt.key文件放在目录中:

    sudo mkdir -p /mnt/gitlab/ssl
    sudo chmod 755 /mnt/gitlab/ssl
    sudo cp gitlab.key gitlab.crt /mnt/gitlab/ssl/
    

    您必须以正确的顺序使用完整的证书链,以防止客户端连接时出现 SSL 错误:首先是服务器证书,然后是所有中间证书,最后是根 CA。

  2. 编辑 /etc/gitlab/gitlab.rb

    nginx['ssl_certificate'] = "/mnt/gitlab/ssl/gitlab.crt"
    nginx['ssl_certificate_key'] = "/mnt/gitlab/ssl/gitlab.key"
    
  3. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

更新 SSL 证书

如果您的 SSL 证书的内容已更新,但没有对 /etc/gitlab/gitlab.rb 进行配置更改,则重新配置极狐GitLab 不会影响 NGINX。相反,您必须使 NGINX 优雅地重新加载现有配置和新证书

sudo gitlab-ctl hup nginx
sudo gitlab-ctl hup registry

配置反向代理或负载均衡器 SSL 终止

默认情况下,如果 external_url 包含 https://,Linux 软件包安装会自动检测是否使用 SSL,并为 SSL 终止配置 NGINX。 但是,如果您将极狐GitLab 配置为在反向代理或外部负载均衡器后面运行,某些环境可能希望在极狐GitLab 应用程序之外终止 SSL。

要防止捆绑的 NGINX 处理 SSL 终止:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['listen_port'] = 80
    nginx['listen_https'] = false
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

外部负载均衡器可能需要访问返回 200 状态码的极狐GitLab 端点(对于需要登录的安装实例,根页面返回 302 重定向到登录页面)。在这种情况下,建议利用健康检查端点

其他捆绑的组件,如 Container Registry、极狐GitLab Pages 或 Mattermost,对代理 SSL 使用类似的策略。使用 https:// 设置特定组件的 *_external_url,并在 nginx[...] 配置前加上组件名称。例如,Container Registry 配置以 registry_ 为前缀:

  1. 编辑 /etc/gitlab/gitlab.rb
  registry_external_url 'https://registry.example.com'

  registry_nginx['listen_port'] = 80
  registry_nginx['listen_https'] = false

相同的格式可用于 Pages(pages_ 前缀)和 Mattermost(mattermost_ 前缀)。

  1. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
  2. 可选。您可能需要配置反向代理或负载均衡器以将某些 headers(例如 HostX-Forwarded-SslX-Forwarded-ForX-Forwarded-Port)转发到极狐GitLab(和 Mattermost,如果您使用)。如果您忘记了这一步,您可能会看到不正确的重定向或错误,例如 “422 Unprocessable Entity” 或 “Can’t verify CSRF token authenticity”。

某些云提供商服务,例如 AWS Certificate Manager (ACM),并非都下载证书。这可以防止它们被用来终止极狐GitLab 实例。如果此类云服务和极狐GitLab 之间需要 SSL,则必须在极狐GitLab 实例上使用另一个证书。

使用自定义 SSL 密码

要更改 SSL 密码:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['ssl_ciphers'] = "CIPHER:CIPHER1"
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

要启用 ssl_dhparam 指令:

  1. 生成 dhparams.pem

    openssl dhparam -out /etc/gitlab/ssl/dhparams.pem 2048
    
  2. 编辑 /etc/gitlab/gitlab.rb

    nginx['ssl_dhparam'] = "/etc/gitlab/ssl/dhparams.pem"
    
  3. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

配置 HTTP/2 协议

默认情况下,当您指定极狐GitLab 实例可通过 HTTPS 访问时,HTTP/2 协议也会启用。

Linux 软件包设置了与 HTTP/2 协议兼容的所需 SSL 密码。

如果您指定自己的自定义 SSL 密码,并且密码在 HTTP/2 密码黑名单,当您尝试访问极狐GitLab 实例时,您会在浏览器中看到 INADEQUATE_SECURITY 错误。在这种情况下,请考虑从密码列表中删除违规密码。仅当您有非常具体的自定义设置时,才需要更改密码。

有关为什么要启用 HTTP/2 协议的更多信息,请查看 NGINX HTTP/2 白皮书

如果更改密码不是一个选项,您可以禁用 HTTP/2 支持:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['http2_enabled'] = false
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    
note HTTP/2 设置仅适用于极狐GitLab 主应用程序,不适用于其他服务,例如极狐GitLab Pages、Container Registry 和 Mattermost。

启用 2-way SSL 客户端身份验证

要要求 Web 客户端使用受信任的证书进行身份验证,您可以启用 2-way SSL:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['ssl_verify_client'] = "on"
    nginx['ssl_client_certificate'] = "/etc/pki/tls/certs/root-certs.pem"
    
  2. 可选。您可以配置 NGINX,在确定客户端没有有效证书之前验证证书链的深度(默认为 1)。编辑 /etc/gitlab/gitlab.rb

    nginx['ssl_verify_depth'] = "2"
    
  3. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

配置 HTTP Strict Transport Security(HSTS)

note HSTS 设置仅适用于极狐GitLab 主应用程序,不适用于其他服务,例如极狐GitLab Pages、Container Registry 和 Mattermost。

HTTP Strict Transport Security(HSTS)默认启用,它通知浏览器他们应该只使用 HTTPS 联系网站。当浏览器访问极狐GitLab 实例一次时,它会记住不再尝试不安全的连接,即使用户明确输入纯 HTTP URL (http://)。浏览器会自动将纯 HTTP URL 重定向到 https:// 变体。

默认情况下, max_age 设置为两年,这是浏览器记住只通过 HTTPS 连接的时间。

要更改最大 age 值:

  1. 编辑 /etc/gitlab/gitlab.rb

    nginx['hsts_max_age'] = 63072000
    nginx['hsts_include_subdomains'] = false
    

    Setting max_age to 0 disables HSTS.

  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

有关 HSTS 和 NGINX 的更多信息,请参阅 https://www.nginx.com/blog/http-strict-transport-security-hsts-and-nginx/

安装自定义公共证书

一些环境连接到外部资源以执行各种任务。Linux 软件包允许这些连接使用 HTTPS,并支持使用自签名证书的连接。极狐GitLab 有自己的 ca-cert 包,您可以通过将各个自定义证书放在 /etc/gitlab/trusted-certs 目录中来添加证书,然后将它们添加到捆绑包中,它们是使用 openssl 的 c_rehash 方法添加的,该方法仅适用于单个证书

极狐GitLab 附带了官方的 CAcert.org 可信根证书颁发机构集合,用于验证证书的真实性。

note 对于使用自签名证书的安装实例,Omnibus 提供了一种管理这些证书的方法。有关其工作原理的更多技术细节,请参阅本页底部的详细信息

如果要安装自定义公共证书:

  1. 从您的私钥证书生成 PEMDER 编码的公共证书。
  2. 仅将公共证书文件复制到/etc/gitlab/trusted-certs 目录中。如果您是一个多节点安装实例,确保将证书拷贝到所有节点。
    • 当配置极狐GitLab 实例以使用自定义公共证书时,默认情况下,极狐GitLab 期望能够找到以实例域名命名的证书,并且以 .crt 为扩展名。比如,如果您的服务器地址为 https://gitlab.example.com,那么证书的名称应该是 gitlab.example.com.crt
    • 如果极狐GitLab 需要连接到一个使用了自定义公共证书的外部资源时,将证书存储到 /etc/gitlab/trusted-certs 目录下,并以 .crt 为扩展。您不必根据相关外部资源的域名来命名文件,尽管使用一致的命名方案会有所帮助。

    为了指定不同的路径和文件名,您可以修改 SSL 证书的默认位置。

  3. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

使用自定义证书链

由于一个已知问题,如果使用自定义证书链,服务器证书、中间证书和根证书必须放入 /etc/gitlab/trusted-certs 目录中的单独文件中,适用于极狐GitLab 本身,或极狐GitLab 必须连接到的外部资源使用自定义证书链这两种情况。

例如,对于极狐GitLab 本身,您可以使用:

  • /etc/gitlab/trusted-certs/example.gitlab.com.crt
  • /etc/gitlab/trusted-certs/example.gitlab.com_intermediate.crt
  • /etc/gitlab/trusted-certs/example.gitlab.com_root.crt

对于极狐GitLab 必须连接的外部资源,您可以使用:

  • /etc/gitlab/trusted-certs/external-service.gitlab.com.crt
  • /etc/gitlab/trusted-certs/external-service.gitlab.com_intermediate.crt
  • /etc/gitlab/trusted-certs/external-service.gitlab.com_root.crt

极狐GitLab 和 SSL 的工作实现细节

Linux 软件包包含自己的 OpenSSL 库,并将所有已编译的程序(例如 Ruby、PostgreSQL 等)链接到该库。该库编译为在 /opt/gitlab/embedded/ssl/certs 中查找证书。

Linux 软件包通过使用 c_rehash 将添加到 /etc/gitlab/trusted-certs/ 的任何证书链接到 /opt/gitlab/embedded/ssl/certs 来管理自定义证书。例如,假设我们将 customcacert.pem 添加到 /etc/gitlab/trusted-certs/

$ sudo ls -al /opt/gitlab/embedded/ssl/certs
total 272
drwxr-xr-x 2 root root   4096 Jul 12 04:19 .
drwxr-xr-x 4 root root   4096 Jul  6 04:00 ..
lrwxrwxrwx 1 root root     42 Jul 12 04:19 7f279c95.0 -> /etc/gitlab/trusted-certs/customcacert.pem
-rw-r--r-- 1 root root 263781 Jul  5 17:52 cacert.pem
-rw-r--r-- 1 root root    147 Feb  6 20:48 README

证书的指纹为 7f279c95,它链接到自定义证书。

当我们发出 HTTPS 请求时会发生什么?让我们以一个简单的 Ruby 程序为例:

#!/opt/gitlab/embedded/bin/ruby
require 'openssl'
require 'net/http'

Net::HTTP.get(URI('https://www.google.com'))

以下是屏幕后面发生的事情:

  1. “require openssl”行导致解释器加载 /opt/gitlab/embedded/lib/ruby/2.3.0/x86_64-linux/openssl.so
  2. Net::HTTP 调用然后尝试读取 /opt/gitlab/embedded/ssl/certs/cacert.pem 中的默认证书包。
  3. SSL 协商。
  4. 服务器发送其 SSL 证书。
  5. 如果发送的证书包含在捆绑包中,则 SSL 将成功完成。
  6. 否则,OpenSSL 可能会通过在预定义的证书目录中,搜索与其指纹匹配的文件来验证其他证书。 例如,如果证书的指纹为“7f279c95”,OpenSSL 将尝试读取 /opt/gitlab/embedded/ssl/certs/7f279c95.0

请注意,OpenSSL 库支持 SSL_CERT_FILESSL_CERT_DIR 环境变量的定义。前者定义了要加载的默认证书包,而后者定义了一个用于搜索更多证书的目录。如果你已将证书添加到“trusted-certs”目录中,这些变量不是必需的。但是,如果由于某种原因需要设置它们,它们可以定义为环境变量。例如:

gitlab_rails['env'] = {"SSL_CERT_FILE" => "/usr/lib/ssl/private/customcacert.pem"}

故障排除

请查看我们的 SSL 故障排除指南