![Nginx HTTP 授权仅适用于 git push](https://linux22.com/image/747676/Nginx%20HTTP%20%E6%8E%88%E6%9D%83%E4%BB%85%E9%80%82%E7%94%A8%E4%BA%8E%20git%20push.png)
我使用 Nginx 托管一个私人 git 服务器。我希望任何人都可以克隆到我的存储库(无需授权),但如果他们尝试推送提交则需要授权。
我的Nginx配置如下:
server {
listen 443 ssl;
server_name git.example.com;
ssl_certificate /fullchain.pem;
ssl_certificate_key /privkey.pem;
location ~ ^.*\.git/(HEAD|info/refs|objects/info/.*|git-(upload|recieve)-pack) {
root /usr/share/nginx/git;
# --- incorrect solution ---
# if ($1 = git-upload-pack) {
# auth_basic "Restricted";
# auth_basic_user_file /usr/share/nginx/htpasswd;
# }
client_max_body_size 0;
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 $realpath_root;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_param PATH_INFO $uri;
fastcgi_param unix:/var/fcgiwrap.socket;
}
据我了解,git push
请求会向我的服务器发送一个git-receive-pack
。我的简单解决方案是$1
使用 if 语句捕获此后缀,但我很快发现这不是 ifs 的正确用法(伊菲斯维尔)。
对于我想要完成的任务,有没有更合适的解决方案?
答案1
git 可以在推送时发送不同的请求(例如/path/to/repo.git/path/in/repo/refs?service=git-upload-pack
或类似),并且您尝试使用平等比较。
尝试这样的事情:
# static repo files for faster cloning over https:
location ~ \.git/objects/(?:[0-9a-f]+/[0-9a-f]+|pack/pack-[0-9a-f]+\.(?:pack|idx))$ {
root /home/git/repositories/;
}
# requests that need to go to git-http-backend:
location ~ \.git/(?:HEAD|info/refs|objects/info/|git-(?:upload|receive)-pack$) {
root /home/git/repositories;
# if upload:
if ( $uri ~* "git-upload-pack$" ) {
auth_basic ...
}
...
}
但作为工作场景,你也可以使用类似这样的方法:
# authorize if user name is specified:
if ( $remote_user != "" ) {
auth_basic ...
}
或者简单地使用不同的 URL(和位置)进行推送,并在授权后重写它。然后你可以配置远程使用不同的推送网址(包含用户名或其他位置):
# with user:
git remote set-url --push origin https://[email protected]/repo/...
# with "rw" location (to force authorization):
git remote set-url --push origin https://git.domail.tld/rw/repo/...
顺便说一句,指令“if”并不比某些顶级正则表达式位置更邪恶(特别是如果它仅应用于特定位置并且不直接影响 http/server 部分)。
但您确实可以在没有“if”的情况下完成所有这些操作(如下例中命名位置所示),但在某些问题上调试并不那么简单(如果您不熟悉 nginx):
location ...condGit... {
root ...;
location ...condA... {
## authorize and supply request to @gitweb:
auth_basic ...
try_files "" @gitweb;
}
location ...condB... {
## authorize and supply request to @gitweb:
auth_basic ...
try_files "" @gitweb;
}
# send anything else to gitweb if it's not a real file (inside root of gitweb):
try_files $uri @gitweb;
location @gitweb {
# ... single location of fcgi wrapper of git http backend ...
}
}