NGINX 配置

特定服务 NGINX 配置

使用者可以通过 gitlab.rb,为不同的服务进行不同的 NGINX 配置。使用 nginx['<some setting>'] 键可以对 GitLab Rails 应用进行配置。其它服务也有类似的键,例如 pages_nginx, mattermost_nginxregistry_nginx。所有 nginx 的可用配置也同样适用于这些服务的 <service_nginx> 配置,并且与 GitLab NGINX 使用相同的默认值。

修改 gitlab.rb 时,用户需要为每个服务分别进行 NGINX 配置。nginx['foo'] 的配置不会复制到服务特定的 NGINX 配置(例如 registry_nginx['foo']mattermost_nginx['foo'] 等等)。例如,要为 GitLab、Mattermost 和 Registry 配置 HTTP 到 HTTPS 的重定向,以下配置应添加到 gitlab.rb

nginx['redirect_http_to_https'] = true
registry_nginx['redirect_http_to_https'] = true
mattermost_nginx['redirect_http_to_https'] = true
note修改 NGINX 配置时应小心谨慎,不正确或不兼容的配置可能会导致服务不可用。

启用 HTTPS

默认情况下,Omnibus GitLab 不使用 HTTPS。如果您想为 gitlab.example.com 启用 HTTPS,有以下两个选项。

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

更改默认的 proxy headers

默认情况下,当您指定了 external_url,Omnibus GitLab 在大多数环境中设置了一些合理的 NGINX proxy headers。

  "X-Forwarded-Proto" => "https",
  "X-Forwarded-Ssl" => "on"

当您已在 external_url 中指定 https 模式。

然而,如果您的实例位于更复杂的设置之中,例如在反向代理之后,您需要调整 proxy headers,以免发生例如 The change you wanted was rejectedCan't verify CSRF token authenticity Completed 422 Unprocessable 的错误。

这可以通过覆盖默认 headers 来实现,例如在 /etc/gitlab/gitlab.rb 中指定:

 nginx['proxy_set_headers'] = {
  "X-Forwarded-Proto" => "http",
  "CUSTOM_HEADER" => "VALUE"
 }

保存文件并重新配置GitLab 使更改生效。

通过这种方法,您可以按需指定 NGINX 支持的任何 header。

配置 trusted_proxies 以及 NGINX real_ip 模块

默认情况下,NGINX 和极狐GitLab 记录所连接客户端的 IP 地址。

如果您的极狐GitLab 实例位于反向代理之后,您可能不需要代理 IP 地址显示为客户地址。

您可以通过添加反向代理到 real_ip_trusted_addresses 列表,使 NGINX 查找一个不同的地址去使用。

# Each address is added to the the NGINX config as 'set_real_ip_from <address>;'
nginx['real_ip_trusted_addresses'] = [ '192.168.1.0/24', '192.168.2.1', '2001:0db8::/32' ]
# other real_ip config options
nginx['real_ip_header'] = 'X-Forwarded-For'
nginx['real_ip_recursive'] = 'on'

选项说明:

默认情况下,Omnibus GitLab 使用 real_ip_trusted_addresses 中的 IP 地址作为 GitLab 信任代理,用户不会使用那些列表中的 IP 进行登录。

保存文件并重新配置GitLab 使更改生效。

配置 PROXY 协议

如果您想使用 PROXY 协议 在极狐GitLab 前面使用 HAProxy 之类的代理,则需要启用此设置。不要忘记根据需要设置 real_ip_trusted_addresses

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

    # Enable termination of ProxyProtocol by NGINX
    nginx['proxy_protocol'] = true
    # Configure trusted upstream proxies. Required if `proxy_protocol` is enabled.
    nginx['real_ip_trusted_addresses'] = [ "127.0.0.0/8", "IP_OF_THE_PROXY/32"]
    
  2. 保存文件并重新配置极狐GitLab,使更改生效。

启用后,NGINX 仅接受这些侦听器上的 PROXY 协议流量。 确保调整您可能拥有的任何其他环境,例如监控检查。

使用非捆绑的网络服务器

默认情况下,Omnibus GitLab 安装捆绑有 NGINX 的极狐GitLab 实例。Omnibus GitLab 允许 gitlab-www 用户访问网络服务器,gitlab-www 用户位于同名的群组中。要允许外部网络服务器访问极狐GitLab 实例,需要将外部网络服务器用户添加到 gitlab-www 群组。

要使用其它 Web 服务器,例如 Apache 或已有的 NGINX 实例,您需要执行以下步骤:

  1. 禁用捆绑的 NGINX

    /etc/gitlab/gitlab.rb 中设置:

       nginx['enable'] = false
    
  2. 设置非捆绑网络服务器用户的用户名

    默认情况下,Omnibus GitLab 没有针对外部网络服务器用户的默认设置,您必须在配置中进行指定。对于 Debian/Ubuntu 操作系统,Apache/NGINX 的默认用户是 www-data,而对于 RHEL/CentOS 操作系统,NGINX 用户是 nginx

    确保您提前安装了 Apache/NGINX,这样已创建了网络服务器用户,否则重新配置时 Omnibus 会失败。

    例如网络服务器用户是 www-data。在 /etc/gitlab/gitlab.rb 中设置:

    ```ruby
    web_server['external_users'] = ['www-data']
    ```	
    

    该设置是一个数组,您可以指定添加多个用户到 gitlab-www 群组。

    执行 sudo gitlab-ctl reconfigure 命令以使更改生效。

    如果您使用 SELinux,并且您的 Web 服务器在 SELinux 限制文件下运行,您可能需要放宽对 Web 服务器的限制。

    确保网络服务器用户对外部网络服务器使用的所有目录具有正确的权限,否则您将收到 failed (XX: Permission denied) while reading upstream 错误。

  3. 将非捆绑的网络服务器添加到受信任代理列表中

    通常 Omnibus GitLab 的可信列表默认为捆绑的 NGINX 配置中,real_ip 模块的配置内容。

    对于非捆绑的网络服务器,需要直接配置该列表,如果网络服务器与极狐GitLab 实例不在同一台机器上,列表中需要包括您的网络服务器 IP 地址。否则,用户将显示为从您的网络服务器的 IP 地址登录。

    ```ruby
    gitlab_rails['trusted_proxies'] = [ '192.168.1.0/24', '192.168.2.1', '2001:0db8::/32' ]
    ```	
    
  4. (可选)使用 Apache 时,设置正确的 GitLab Workhorse

    Apache 需要连接到 TCP 端口而不是 UNIX 套接字。要允许 GitLab Workhorse 监听 TCP 端口(默认为 8181),编辑 /etc/gitlab/gitlab.rb

    ```ruby
    gitlab_workhorse['listen_network'] = "tcp"
    gitlab_workhorse['listen_addr'] = "127.0.0.1:8181"
    ```
    

    执行 sudo gitlab-ctl reconfigure 命令以使更改生效。

  5. 下载正确的网络服务器配置

    访问 GitLab recipes repository,在 webserver 目录中,查找 Omnibus 配置。根据您是否使用 SSL,挑选正确的配置文件。您唯一需要修改的是 YOUR_SERVER_FQDN,修改为您自己的 FQDN,如果您使用 SSL,则修改为您的 SSL 密钥当前所在的位置。您可能还需要更改日志文件的位置。

设置 NGINX 监听地址

默认情况下,NGINX 将接受所有本地 IPv4 地址上的传入连接。您可以更改 /etc/gitlab/gitlab.rb 上的地址列表。

 # Listen on all IPv4 and IPv6 addresses
nginx['listen_addresses'] = ["0.0.0.0", "[::]"]
registry_nginx['listen_addresses'] = ['*', '[::]']
mattermost_nginx['listen_addresses'] = ['*', '[::]']
pages_nginx['listen_addresses'] = ['*', '[::]']

设置 NGINX 监听端口

默认情况下,NGINX 将监听 external_url 中的指定端口,或使用正确的端口(HTTP 为 80,HTTPS 为 443)。如果您在反向代理后运行极狐GitLab,您可能想要使用其它的监听端口。以使用 8081 为例:

nginx['listen_port'] = 8081

NGINX 日志的详细级别

默认情况下,NGINX 会以 error 详细级别记录日志。您可以通过更改日志级别以不同的级别登录。例如,要启用 debug 日志记录:

nginx['error_log_level'] = "debug"

可以从 NGINX 文档中找到有效值。

设置 Referrer-Policy header

默认情况下,极狐GitLab 所有响应的 Referrer-Policy header 设置为 strict-origin-when-cross-origin

这使得客户端在发出同源请求时,发送完整的 URL 作为 referrer,但仅在发出跨域请求时发送源。

将该表头设置为不同的值:

nginx['referrer_policy'] = 'same-origin'

您也可以禁用该 header,使客户端使用默认设置:

nginx['referrer_policy'] = false

注意,将其设置为 originno-referrer,会破坏极狐GitLab 中需要完整引用 URL 的某些功能。

禁用 Gzip 压缩

默认情况下,极狐GitLab 对超过 10240 字节的文本数据启用 Gzip 压缩。要禁用此行为:

nginx['gzip_enabled'] = false
notegzip 设置仅适用于极狐GitLab 主应用,不适用于其它服务。

禁用代理请求缓冲

可以通过更改 request_buffering_off_path_regex 在特定位置选择性地禁用请求缓冲。

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

    nginx['request_buffering_off_path_regex'] = "/api/v\\d/jobs/\\d+/artifacts$|/import/gitlab_project$|\\.git/git-receive-pack$|\\.git/gitlab-lfs/objects|\\.git/info/lfs/objects/batch$"
    
  2. 重新配置极狐GitLab,并 HUP NGINX,使其优雅地重新加载更新的配置:

    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl hup nginx
    

配置 robots.txt

要为您的实例配置 robots.txt,指定一个自定义的 robots.txt 文件,并添加自定义 NGINX 配置。

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

    nginx['custom_gitlab_server_config'] = "\nlocation =/robots.txt { alias /path/to/custom/robots.txt; }\n"
    
  2. 重新配置极狐GitLab:

    sudo gitlab-ctl reconfigure
    

在 server block 中添加自定义 NGINX 设置

请注意,如果在您的 gitlab.rb 文件中定义了相同的设置,这些自定义设置可能会发生冲突。

如果出于某种原因,您需要将自定义设置添加到 NGINX server block 中,您可以使用以下设置。

# Example: block raw file downloads from a specific repository
nginx['custom_gitlab_server_config'] = "location ^~ /foo-namespace/bar-project/raw/ {\n deny all;\n}\n"

执行 gitlab-ctl reconfigure 命令,重写 NGINX 配置并重启 NGINX。

定义的字符串将被插入到 /var/opt/gitlab/nginx/conf/gitlab-http.conf 中的 server block 末尾。

注意

  • 如果您在添加新的 location,需要在字符串中包含以下内容,或已包含在 NGINX 配置中。

    proxy_cache off;
    proxy_pass http://gitlab-workhorse;
    

    没有以上配置,任何 sub-location 将返回 404。

  • 不能添加根路径 / location 或 /assets location,因为已经存在于 gitlab-http.conf

在 NGINX 配置中插入自定义设置

如果您需要在 NGINX 配置中插入自定义设置,例如包含已存在的 server blocks,您可以使用如下设置。

# Example: include a directory to scan for additional config files
nginx['custom_nginx_config'] = "include /etc/nginx/conf.d/*.conf;"

执行 gitlab-ctl reconfigure,重写 NGINX 配置并重启 NGINX。

定义的字符串将被插入到 /var/opt/gitlab/nginx/conf/nginx.conf 中的 http block 末尾。

自定义错误页面

您可以使用 custom_error_pages 修改默认的极狐GitLab 错误页面的文案。适用于任何有效的 HTTP 错误码;例如 404,502。

参考以下示例修改默认的 404 错误页面。

nginx['custom_error_pages'] = {
  '404' => {
    'title' => 'Example title',
    'header' => 'Example header',
    'message' => 'Example message'
  }
}

将生成下方的 404 页面。

custom 404 error page

执行 gitlab-ctl reconfigure,重写 NGINX 配置并重启 NGINX。

使用已有的 Passenger/NGINX 实例

在某些情况下,您可能想要极狐GItLab 实例使用已有的 Passenger/NGINX 实例,但同时保留使用 Omnibus 安装包进行升级和安装时的便利性。

note当禁用 NGINX 时,您将无法访问 Omnibus 的其它服务,例如 Grafana,Mattermost 等等,除非您在 nginx.conf 中手动添加。

配置

首先,您需要设置 /etc/gitlab/gitlab.rb 以禁用内建的 NGINX 和 Puma。

# Define the external url
external_url 'http://git.example.com'

# Disable the built-in nginx
nginx['enable'] = false

# Disable the built-in puma
puma['enable'] = false

# Set the internal API URL
gitlab_rails['internal_api_url'] = 'http://git.example.com'

# Define the web server process user (ubuntu/nginx)
web_server['external_users'] = ['www-data']

确保执行 sudo gitlab-ctl reconfigure 命令使更改生效。

Vhost (server block)

然后,在您的自定义 Passenger/NGINX 实例中,创建以下站点配置文件:

upstream gitlab-workhorse {
  server unix://var/opt/gitlab/gitlab-workhorse/sockets/socket fail_timeout=0;
}

server {
  listen *:80;
  server_name git.example.com;
  server_tokens off;
  root /opt/gitlab/embedded/service/gitlab-rails/public;

  client_max_body_size 250m;

  access_log  /var/log/gitlab/nginx/gitlab_access.log;
  error_log   /var/log/gitlab/nginx/gitlab_error.log;

  # Ensure Passenger uses the bundled Ruby version
  passenger_ruby /opt/gitlab/embedded/bin/ruby;

  # Correct the $PATH variable to included packaged executables
  passenger_env_var PATH "/opt/gitlab/bin:/opt/gitlab/embedded/bin:/usr/local/bin:/usr/bin:/bin";

  # Make sure Passenger runs as the correct user and group to
  # prevent permission issues
  passenger_user git;
  passenger_group git;

  # Enable Passenger & keep at least one instance running at all times
  passenger_enabled on;
  passenger_min_instances 1;

  location ~ ^/[\w\.-]+/[\w\.-]+/(info/refs|git-upload-pack|git-receive-pack)$ {
    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
    error_page 418 = @gitlab-workhorse;
    return 418;
  }

  location ~ ^/[\w\.-]+/[\w\.-]+/repository/archive {
    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
    error_page 418 = @gitlab-workhorse;
    return 418;
  }

  location ~ ^/api/v3/projects/.*/repository/archive {
    # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
    error_page 418 = @gitlab-workhorse;
    return 418;
  }

  # Build artifacts should be submitted to this location
  location ~ ^/[\w\.-]+/[\w\.-]+/builds/download {
      client_max_body_size 0;
      # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
      error_page 418 = @gitlab-workhorse;
      return 418;
  }

  # Build artifacts should be submitted to this location
  location ~ /ci/api/v1/builds/[0-9]+/artifacts {
      client_max_body_size 0;
      # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
      error_page 418 = @gitlab-workhorse;
      return 418;
  }

  # Build artifacts should be submitted to this location
  location ~ /api/v4/jobs/[0-9]+/artifacts {
      client_max_body_size 0;
      # 'Error' 418 is a hack to re-use the @gitlab-workhorse block
      error_page 418 = @gitlab-workhorse;
      return 418;
  }


  # For protocol upgrades from HTTP/1.0 to HTTP/1.1 we need to provide Host header if its missing
  if ($http_host = "") {
  # use one of values defined in server_name
    set $http_host_with_default "git.example.com";
  }

  if ($http_host != "") {
    set $http_host_with_default $http_host;
  }

  location @gitlab-workhorse {

    ## https://github.com/gitlabhq/gitlabhq/issues/694
    ## Some requests take more than 30 seconds.
    proxy_read_timeout      3600;
    proxy_connect_timeout   300;
    proxy_redirect          off;

    # Do not buffer Git HTTP responses
    proxy_buffering off;

    proxy_set_header    Host                $http_host_with_default;
    proxy_set_header    X-Real-IP           $remote_addr;
    proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto   $scheme;

    proxy_pass http://gitlab-workhorse;

    ## The following settings only work with NGINX 1.7.11 or newer
    #
    ## Pass chunked request bodies to gitlab-workhorse as-is
    # proxy_request_buffering off;
    # proxy_http_version 1.1;
  }

  ## Enable gzip compression as per rails guide:
  ## http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression
  ## WARNING: If you are using relative urls remove the block below
  ## See config/application.rb under "Relative url support" for the list of
  ## other files that need to be changed for relative url support
  location ~ ^/(assets)/ {
    root /opt/gitlab/embedded/service/gitlab-rails/public;
    gzip_static on; # to serve pre-gzipped version
    expires max;
    add_header Cache-Control public;
  }

  ## To access Grafana
  location /-/grafana/ {
    proxy_pass http://localhost:3000/;
  }

  error_page 502 /502.html;
}

不要忘记将上面示例中的 git.example.com 更新为您的服务器 URL。

如果您收到 403 forbidden 返回,可能是您没有在 /etc/nginx/nginx.conf 中启用 passenger,只需取消注释即可:

# include /etc/nginx/passenger.conf;

然后执行 sudo service nginx reload 命令。

启用/禁用 nginx_status

默认情况下,NGINX 健康检查端点配置在 127.0.0.1:8060/nginx_status,以监控您的 NGINX 服务器状态。

展示以下信息

Active connections: 1
server accepts handled requests
 18 18 36
Reading: 0 Writing: 1 Waiting: 0
  • Active connections - 开放的连接总数。
  • 展示 3 个指标数字。
    • 所有接受的连接。
    • 所有处理的连接。
    • 处理的请求总数。
  • Reading:NGINX 读取的请求 header。
  • Writing:NGINX 读取请求体,处理请求,或将响应写入客户端。
  • Waiting:Keep-alive 连接。该数字取决于 keepalive-timeout。

配置项

编辑 /etc/gitlab/gitlab.rb

nginx['status'] = {
  "listen_addresses" => ["127.0.0.1"],
  "fqdn" => "dev.example.com",
  "port" => 9999,
  "options" => {
    "access_log" => "on", # Disable logs for stats
    "allow" => "127.0.0.1", # Only allow access from localhost
    "deny" => "all" # Deny access to anyone else
  }
}

如果您发现该服务不适用于您当前的基础设施,您可以通过以下命令禁用:

nginx['status'] = {
  'enable' => false
}

确保执行 sudo gitlab-ctl reconfigure 命令使更改生效。

警告

为了确保可以访问用户上传的内容,您的 NGINX 用户(通常为 www-data)应被添加到 gitlab-www 群组中。使用以下命令:

sudo usermod -aG gitlab-www www-data

模板

处理替代 Puma 的 Passenger 配置和缺少 HTTPS(尽管可以启用)外,这些文件大部分与以下内容相同:

不要忘记重启 NGINX,加载新的配置(在 Debian 系统中为 sudo service nginx restart)。

故障排查

400 Bad Request: too many Host headers

确保在 nginx['custom_gitlab_server_config'] 设置中没有 proxy_set_header 配置,而是在 gitlab.rb 文件中使用 ‘proxy_set_headers’ 配置。

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure

从 GitLab 10 开始,Omnibus GitLab 包默认不再支持 TLSv1 协议。在与 GitLab 实例交互时,这可能会导致某些基于 Java 的旧 IDE 客户端出现连接问题。我们强烈建议您升级服务器上的密码。

如果无法更改此服务器,则可以通过更改 /etc/gitlab/gitlab.rb 中的值来默认返回旧协议:

nginx['ssl_protocols'] = "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"

私钥和证书不匹配

如果在 NGINX 日志(Omnibus 默认为 /var/log/gitlab/nginx/current)中看到 x509 certificate routines:X509_check_private_key:key values mismatch),您的私钥和证书不匹配。

要解决该问题,您需要将正确的私钥与您的证书相匹配。

为确保您拥有正确的密钥和证书,您可以确保私钥和证书的模数匹配:

/opt/gitlab/embedded/bin/openssl rsa -in /etc/gitlab/ssl/gitlab.example.com.key -noout -modulus | /opt/gitlab/embedded/bin/openssl sha256

/opt/gitlab/embedded/bin/openssl x509 -in /etc/gitlab/ssl/gitlab.example.com.crt -noout -modulus| /opt/gitlab/embedded/bin/openssl sha256

一旦您确认它们匹配,您需要重新配置并重新加载 NGINX:

sudo gitlab-ctl reconfigure
sudo gitlab-ctl hup nginx

Request Entity Too Large

如果您在 NGINX 日志 中看到 Request Entity Too Large,您需要增加 Client Max Body Size。如果您增加了最大导入大小,可能会遇到此错误。在基于 Kubernetes 的安装中,该设置的名称不同

要增加 client_max_body_size,您需要在 /etc/gitlab/gitlab.rb 中设置该值:

nginx['client_max_body_size'] = '250m'

确保执行 sudo gitlab-ctl reconfiguresudo gitlab-ctl hup nginx 命令,使 NGINX 加载更新配置。要增加 client_max_body_size

  1. 编辑 /etc/gitlab/gitlab.rb 并设置更优值:

    nginx['client_max_body_size'] = '250m'
    
  2. 重新配置极狐Gitlab 和 HUP NGINX,平滑加载更新的配置:

    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl hup nginx
    

当使用 SELinux 和外部 NGINX 时出现 502: Bad Gateway

在启用了 SELinux 的 Linux 服务器上,设置外部 NGINX 后,访问 GitLab UI 时可能会观察到错误 502:Bad Gateway。您还可以在 NGINX 的日志中看到错误:

connect() to unix:/var/opt/gitlab/gitlab-workhorse/sockets/socket failed (13:Permission denied) while connecting to upstream

选择以下选项之一进行修复:

  • 更新到 14.3 或更高版本,其中包含更新的 SELinux 策略。
  • 手动获取和更新策略:

    wget https://gitlab.com/gitlab-org/omnibus-gitlab/-/raw/a9d6b020f81d18d778fb502c21b2c8f2265cabb4/files/gitlab-selinux/rhel/7/gitlab-13.5.0-gitlab-shell.pp
    semodule -i gitlab-13.5.0-gitlab-shell.pp