Software Adventures - cgit

Hello all! This week I had the wonderful privilege of installing cgit on my VPS. It was not a pleasant experience, so in the interests of saving others a lot of trouble, I've decided to write a post about what configuration ended up working for me.

Here's the relevant code from my nginx configuration file:

location /git {
	alias /usr/share/webapps/cgit;
	try_files $uri @cgit;
}
location @cgit {
	root /usr/share/webapps/cgit;
	include fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $document_root/cgit.cgi;
	fastcgi_split_path_info ^(/git/?)(.+)$;
	fastcgi_param PATH_INFO $fastcgi_path_info;
	fastcgi_param QUERY_STRING $args;
	fastcgi_param HTTP_HOST $server_name;
	fastcgi_pass unix:/run/fcgiwrap.sock;
}
location ~ /git/.+/(info|refs|git-upload-pack) {
	include fastcgi_params;
	fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
	fastcgi_param PATH_INFO $uri;
	fastcgi_param GIT_HTTP_EXPORT_ALL "";
	fastcgi_param GIT_PROJECT_ROOT /srv;
	fastcgi_pass unix:/run/fcgiwrap.sock;
}

This obviously goes in the server section of your configuration file. It hosts cgit on /git/ rather than /, as I already have other content at the root of my domain and don't want to use a subdomain. There's a couple things going on here, so let's look at each of them individually.

location /git {
	alias /usr/share/webapps/cgit;
	try_files $uri @cgit;
}

cgit requires some static files in order to function. As far as I know, these files are `cgit.png`, `cgit.css`, `favicon.ico`, and `robots.txt`, but those details shouldn't matter. The important thing is that cgit won't serve those files for us, we need nginx to do it. The simplest way to do that is to just use the `try_files` directive; if nginx can get the file, great, we serve it. Otherwise, we move to the `@cgit` section.

location @cgit {
	root /usr/share/webapps/cgit;
	include fastcgi_params;
	fastcgi_param SCRIPT_FILENAME $document_root/cgit.cgi;
	fastcgi_split_path_info ^(/git/?)(.+)$;
	fastcgi_param PATH_INFO $fastcgi_path_info;
	fastcgi_param QUERY_STRING $args;
	fastcgi_param HTTP_HOST $server_name;
	fastcgi_pass unix:/run/fcgiwrap.sock;
}

This is where the magic happens. What this section does is ask fastcgi to ask cgit to give us a page to display. I've done some testing, and as far as I can tell, these lines are all mandatory; other internet guides list some other `fastcgi_param` lines, but I've found most of these to be redundant due to the `include fastcgi_params` directive. The `fastcgi_split_path_info` directive is what caused me so much trouble getting my setup working, and what so many other guides neglected to mention at all.

location ~ /git/.+/(info|refs|git-upload-pack) {
	include fastcgi_params;
	fastcgi_param SCRIPT_FILENAME /usr/lib/git-core/git-http-backend;
	fastcgi_param PATH_INFO $uri;
	fastcgi_param GIT_HTTP_EXPORT_ALL "";
	fastcgi_param GIT_PROJECT_ROOT /srv;
	fastcgi_pass unix:/run/fcgiwrap.sock;
}

This final section is technically optional, but is almost certainly something you want to include anyways. What this does is pass certain requests (specifically, `git pull` and `git clone` requests) to the `git-http-backend` program, which comes with the standard git package on most distros (so, no installation is necessary). The reason we do this rather than just letting cgit handle it is that `git-http-backend`, also known as the "smart" http backend, is *significantly* faster than the "dumb" http backend you'd get with a static file server or cgit. Since it comes at essentially zero cost, and substantially improves the performance of your server, it's a very good idea to use it.

I hope this has helped anyone else having trouble with installing cgit! As a final note, I'll post my `/etc/cgitrc`, although there's nothing particularly interesting going on there. Good luck!

css=/cgit.css
logo=/git/cgit.png
cache-size=1024
snapshots=tar.gz zip 
remove-suffix=1
clone-url=https://$HTTP_HOST/git/$CGIT_REPO_URL.git
enable-http-clone=1
enable-git-config=1
scan-path=/srv/git/

If you're looking for an example, my cgit server can be viewed at:

LOH Git