背景与问题现象最近入职了一家正在成长期的公司代码评审和CICD流程机制很不完善于是我决定搭建一套GerritJenkins流水线在搭建和配置Gerrit代码评审系统时为了实现网页端Web UI的免密自动登录我们通常会采用Nginx Basic Auth Gerrit HTTP Auth的托管认证架构。然而在架构搭建完成后团队成员在本地使用Git命令行通过HTTP/HTTPS协议克隆Clone或推送Push代码时却遭遇了失败报错现象命令行提示401 Unauthorized或403 Forbidden即使输入了Gerrit网页端生成的HTTP CredentialsHTTP专用密码 也依然无法通过验证。诡异的是如果绕过Nginx直接使用Gerrit自身的8080端口进行克隆如git clone http://172.16.31认证和克隆完全正常。 深度排查与根因分析通过对比8080端口与Nginx代理端口的克隆表现问题被精准锁定在Nginx反向代理层。Gerrit的/a/路径机制在Gerrit的路由规则中带有/a/的URL例如/a/p/project_name代表强制认证的Git操作路径。当Git客户端请求该路径时会携带包含Gerrit HTTP专用密码的Authorization请求头。Gerrit收到后会自行解析并校验。Nginx与Git凭证的两重认证冲突在初始的Nginx配置中由于没有对Git的特定路径做分流所有的请求都会落入location /规则中。这就导致了致命的冲突凭证误判location /开启了Nginx自身的auth_basic读取.htpasswd。当Git客户端带着Gerrit的专用密码请求过来时Nginx误以为这是给自己的验证凭证。双重拦截因为Gerrit专用密码与Nginx的.htpasswd密码不一致Nginx直接在最外层拦截并返回了401错误导致请求根本没有到达Gerrit服务端。️ 解决方案要解决这个问题核心思路是将网页端请求与Git命令行请求在Nginx层进行分流。对Git命令行及公开克隆路径关闭Nginx层的认证将其原封不动地透传给Gerrit自身去控权。同时为了防止大项目克隆时出现HTTP缓冲区溢出、中断或超时还需要在Nginx中加入针对Git大文件流的优化参数。 终极 Nginx 配置文件以下是经过优化和整合后的完整nginx.conf核心配置server{listen80;server_name172.16.31.59;# 1. 清除网页端认证缓存的特殊路径location/logout{auth_basic off;return401;}# 限制上传文件的最大体积支持大单品、大仓库推送client_max_body_size 20480M;# 2. 【核心修复】合并所有 Git 命令行、工具链以及匿名/公开克隆路径# 正则匹配说明# /a/ 认证克隆、/tools/ 客户端钩子工具# /p/ /info/refs /git- 开头的通用 Git 智能 HTTP 协议标准路径location ~* ^/(a|tools|p|info/refs|git-upload-pack|git-receive-pack){# 关键关闭 Nginx 层认证让 Git 客户端的专用密码直接透传给 Gerrit 校验auth_basic off;proxy_pass http://127.0.0.1:8080;proxy_set_header Host$host;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;# 针对 Git 大文件传输流Stream的优化proxy_http_version1.1;proxy_set_header Connection;# 防止大项目克隆/推送时由于网络慢或数据量大导致 Nginx 触发 504 超时proxy_connect_timeout 600s;proxy_read_timeout 600s;proxy_send_timeout 600s;}# 3. 网页端Web UI与 Gerrit REST API 请求location /{# 仅对网页登录和常规浏览开启 Nginx Basic Authauth_basicGerrit Code Review;auth_basic_user_file /etc/nginx/.htpasswd;# 认证成功后将用户名通过请求头传递给 Gerrit 实现免密登录proxy_set_header X-Remote-User$remote_user;proxy_pass http://127.0.0.1:8080;proxy_set_header Host$host;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;}} 总结与避坑心得路由优先级在Nginx中正则匹配location ~*的优先级高于通用前缀匹配location /。利用这一特性我们可以完美剥离Git流量。不仅仅是/a/除了带认证的/a/和工具路径/tools/还要把不带/a/的匿名克隆路径如/p/、/info/refs也一并对Nginx释放。否则团队成员在拉取公开项目或未登录克隆时依然会被Nginx的弹窗拦截。协议优化由于Git传输大文件是流式数据配置proxy_http_version 1.1并清除Connection头能有效维持持久连接规避RPC failed; curl 56 Recv failure错误。如果这篇博客对你有帮助欢迎点赞、收藏并分享给正在填坑的小伙伴如果有更优雅的配置方案欢迎在评论区交流。 流。