Git-http-backend与Nginx配置问题:Git服务器重定向超限
Debian 11 ARM Git服务器重定向问题排查与修复
环境与现状
- 系统:Debian 11 ARM
- 已安装软件:git、stagit、nginx、fcgiwrap、apache2-utils
- 域名:git.mydomain.com(通过Cloudflare解析并开启CDN)
- Git仓库存储目录:/home/git(git用户主目录,包含repo1.git、repo2.git等仓库,所有仓库均存在
git-daemon-export-ok文件) - Stagit静态页面目录:/var/www/git,目录结构如下:
/var/www/git ├── favicon.png ├── index.html ├── logo.png ├── repo1.git │ ├── atom.xml │ ├── commit │ ├── files.html │ ├── index.html -> log.html │ ├── log.html │ ├── logo.png -> ../logo.png │ ├── refs.html │ ├── style.css -> ../style.css │ └── tags.xml ├── repo2.git │ ├── atom.xml │ ├── commit │ ├── files.html │ ├── index.html -> log.html │ ├── log.html │ ├── logo.png -> ../logo.png │ ├── refs.html │ ├── style.css -> ../style.css │ └── tags.xml └── style.css
错误现象
- 执行克隆命令时触发循环重定向:
git clone git.mydomain.com/repo1.git Cloning into 'stagit'... fatal: unable to access 'https://git.mydomain.com/repo1.git/': Maximum (20) redirects followed
- curl测试返回301循环重定向:
curl -i https://git.mydomain.com/repo1.git/info/refs\?service\=git-upload-pack HTTP/2 301 date: Mon, 08 May 2023 18:13:14 GMT content-type: text/html location: https://git.mydomain.com/repo1.git/info/refs?service=git-upload-pack cf-cache-status: DYNAMIC report-to: {"endpoints":[{"url":"https:\/\/a.nel.cloudflare.com\/report\/v3?s=DSwlz8PC%2Fwxsz35EsZTayjherWuZIeRCUgeP5fh1i6FvbNPndKIzAVIqvGlnPUKj%2Ba%2BqQiLvkw5w8409hOPR7ahtPyfEUD9jMs8irWWh6AHxnw8xxBN4sTtqFCWX"}],"group":"cf-nel","max_age":604800} nel: {"success_fraction":0,"report-to":"cf-nel","max_age":604800} strict-transport-security: max-age=31536000; includeSubDomains; preload x-content-type-options: nosniff server: cloudflare cf-ray: 7c43ace7ebcc492b-SIN alt-svc: h3=":443"; ma=86400, h3-29=":443"; ma=86400 <html> <head><title>301 Moved Permanently</title></head> <body> <center><h1>301 Moved Permanently</h1></center> <hr><center>nginx/1.24.0</center> </body> </html>
问题原因
- 请求匹配逻辑失效:实际请求路径为
/repo1.git,但原配置中仅匹配/home/git/开头的路径,这部分规则完全不会触发,导致Git智能服务请求无法被路由到git-http-backend。 - 静态资源处理冲突:Nginx尝试将
/repo1.git当作静态目录处理,因目录末尾缺少斜杠触发301重定向,重定向后的URL再次进入相同逻辑,形成循环。
修正后的Nginx配置
server { listen 80; listen [::]:80; server_name git.mydomain.com; return 301 https://$server_name$request_uri; } server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name git.mydomain.com; root /var/www/git; index index.html index.htm; access_log /var/log/nginx/git.mydomain.com-access.log; error_log /var/log/nginx/git.mydomain.com-error.log; gzip off; ssl_certificate /etc/nginx/cert/git.mydomain.com.pem; ssl_certificate_key /etc/nginx/cert/git.mydomain.com.key; # 匹配所有Git仓库路径,处理智能服务请求 location ~ ^(/.*\.git)(/.*)?$ { # 标记需要认证的推送操作 set $auth_required "0"; if ($arg_service = git-receive-pack) { set $auth_required "1"; } if ($uri ~ ^/.*\.git/git-receive-pack$) { set $auth_required "1"; } # 推送请求启用HTTP Basic认证 if ($auth_required = "1") { auth_basic "Require password to push to git.mydomain.com:"; auth_basic_user_file /etc/nginx/.htpasswd; } include fastcgi_params; fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend; fastcgi_param GIT_HTTP_EXPORT_ALL ""; fastcgi_param GIT_PROJECT_ROOT /home/git; fastcgi_param REMOTE_USER $remote_user; fastcgi_param PATH_INFO $1; fastcgi_pass unix:/var/run/fcgiwrap.socket; } # 优先返回Stagit生成的静态页面 location / { try_files $uri $uri/ =404; } }
配置说明
- 核心匹配规则:
^(/.*\.git)(/.*)?$覆盖所有Git仓库的请求路径,确保智能服务请求能被正确路由。 - 认证逻辑:仅对推送操作(
git-receive-pack)启用HTTP Basic认证,拉取操作无需认证。 - 路径传递修正:通过
PATH_INFO $1正确传递仓库路径(如/repo1.git),让git-http-backend能找到/home/git下的对应仓库。 - 静态页面兼容:默认location优先返回Stagit生成的静态文件,保证仓库的静态浏览页面正常访问。
验证步骤
- 重启Nginx服务:
sudo systemctl restart nginx - 测试克隆:
git clone https://git.mydomain.com/repo1.git - 测试推送(需输入认证密码):在克隆仓库中修改文件后执行
git push origin main - 验证静态页面:访问
https://git.mydomain.com/repo1.git确认Stagit页面正常显示
内容的提问来源于stack exchange,提问作者Dejavu Moe
相关产品推荐
相关产品推荐

