Sounds simple, right. Plug in cgit and git-http-backend with nginx to get nice web interface and working clone URL. And pushable too, of course. It turned out not to be quite that easy, but seems doable with some quirks.
There are plenty of instructions for parts of this lying around, but didn't find one that catches 'em all, so needed to some cuttin', pastin' and retryin'. The end result nginx configuration:
location ~ "(?x)^/git(?<path>/.*/(?:HEAD '
info/refs '
objects/(?:info/[^/]+ '
[0-9a-f]{2}/[0-9a-f]{38} '
pack/pack-[0-9a-f]{40}\.(?:pack '
idx)) '
git-upload-pack))$" {
error_page 491 = @auth;
if ($query_string = service=git-receive-pack) {
return 491;
}
client_max_body_size 0;
fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
include fastcgi_params;
fastcgi_param GIT_HTTP_EXPORT_ALL "";
fastcgi_param GIT_PROJECT_ROOT /srv/git;
fastcgi_param PATH_INFO $path;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
location ~ "^/git(?<path>/.*/git-receive-pack)$" {
error_page 491 = @auth;
return 491;
}
location @auth {
auth_basic "Git write access";
auth_basic_user_file /srv/git/.htpasswd;
client_max_body_size 0;
fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
include fastcgi_params;
fastcgi_param GIT_HTTP_EXPORT_ALL "";
fastcgi_param GIT_PROJECT_ROOT /srv/git;
fastcgi_param PATH_INFO $path;
fastcgi_param REMOTE_USER $remote_user;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
location ~ ^/git(?<path>/.*)$ {
alias /usr/share/cgit;
try_files $1 @cgit;
}
location @cgit {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
fastcgi_param PATH_INFO $path;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_param CGIT_CONFIG /srv/git/.cgitrc;
fastcgi_pass unix:/var/run/fcgiwrap.socket;
}
cgit also requires configuration, it could be done system wide with /etc/cgitrc, but I opted defining CGIT_CONFIG
environment variable to point to a custom path, the .cgitrc ended up like something like this:
css=/git/cgit.css
logo=/git/cgit.png
virtual-root=/git
clone-url=https://$HTTP_HOST/git/$CGIT_REPO_URL
scan-path=/srv/git
The binary and socket paths, and cgit data path, are those used by Debian default configuration, may need adjustment for different installations. Tried to get rid of the virtual-root directive in cgitrc, but that would require setting SCRIPT_PATH
, which fcgiwrap eats away.
For more access control, you could grab the repository name from the request paths: "(?<path>/(?<repo>.*)/"
, and integrate the $repo into auth_basic_user_file
.