RSSAmplifier

Posts on JFR's Musings · Jan 2, 2026

Selfhosting git with cgit and git-http-backend

0
Sign in to vote or save

JFR's Musings

I’ve been self-hosting my git repositories for some time, but I’ve just upgraded them to use git-http-backend. Previously, clones were served by cgit (and before that by gitweb), which both present as a “dumb HTTP transport”. The smart protocol is much faster, though, especially with relatively high latency like my repositories tend to have. Git includes a CGI implementation of this called git-http-backend, and even comes with instructions to use it with Apache. Thankfully that made it pretty simple to translate to nginx… at least, since I already have fcgiwrap set up for cgit.

You’ll need cgit, fcgiwrap, xinetd, and nginx. You’ll also have to adapt paths from your setup; mine assumes you’re on Gentoo and store repos under /data/git/git/.


/etc/nginx/nginx.conf

Add these location blocks. Note that the relative order of these is important. You’ll also want to make sure any other regex blocks which might match them are listed later in the config.

location ~ "^/git/(.*\.git/objects/[0-9a-f]{2}/[0-9a-f]{38})$" {
	root /data/git/;
	add_header Handler "root /git" always;
}
location ~ "^/git/(.*\.git/(HEAD|info/refs|objects/(info/[^/]+|[0-9a-f]{2}/[0-9a-f]{38}|pack/pack-[0-9a-f]{40}\.(pack|idx))|git-(upload|receive)-pack))$" {
	fastcgi_split_path_info ^(/git)(/.+)$;
	fastcgi_pass 127.0.0.1:1733;
	include fastcgi-git-http-backend.conf;
	add_header Handler "git-http-backend" always;
}
location ~ ^/git/ {
	fastcgi_split_path_info ^(/git)(/.+)$;
	fastcgi_pass 127.0.0.1:1733;
	include fastcgi-cgit.conf;
}
location ^~ /cgit/ {
	alias /usr/share/webapps/cgit/9999/htdocs/;
}
...

/etc/xinetd.d/fcgi

service fcgi
{
	type            = unlisted
	socket_type     = stream
	wait            = yes
	user            = cgit
	group           = cgit
	umask           = 002
	protocol        = tcp
	log_on_failure += USERID HOST
	port            = 1733
	bind            = 127.0.0.1
	server          = /usr/sbin/fcgiwrap
	server_args     = -f
	passenv         =
}

/etc/nginx/fastcgi-cgit.conf

# the usual fastcgi params, plus:
fastcgi_param  GIT_PROJECT_ROOT   /data/git/git/;
fastcgi_param  SCRIPT_FILENAME    /usr/share/webapps/cgit/9999/hostroot/cgi-bin/cgit.cgi;
fastcgi_param  SCRIPT_NAME        /git/;
fastcgi_param  DOCUMENT_ROOT      /usr/share/webapps/cgit/9999/hostroot/;
fastcgi_param  PATH_INFO          $fastcgi_path_info;

/etc/nginx/fastcgi-git-http-backend.conf

# the usual fastcgi params, plus:
fastcgi_param  GIT_PROJECT_ROOT   /data/git/git/;
fastcgi_param  SCRIPT_FILENAME    /usr/libexec/git-core/git-http-backend;
fastcgi_param  SCRIPT_NAME        /git/;
fastcgi_param  PATH_INFO          $fastcgi_path_info;

/etc/cgitrc

cache-size=1000
source-filter=/usr/lib64/cgit/filters/syntax-highlighting.py
about-filter=/usr/lib64/cgit/filters/about-formatting.sh
email-filter=lua:/usr/lib64/cgit/filters/email-gravatar.lua
readme=:README.html
readme=:README.md
readme=:README.txt
readme=:README
agefile=last-modified
enable-blame=1
enable-commit-graph=1
enable-git-config=1
clone-prefix=https://jfr.im/git
enable-http-clone=0
enable-log-filecount=1
enable-log-linecount=1
enable-subject-links=1
section-from-path=1
repository-sort=age
enable-index-owner=0
robots=
strict-export=git-daemon-export-ok
scan-path=/data/git/git

Read the original on jfr.im

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.