For to be to make you smarter. For to be to get you dead.

gitweb and nginx 2012-01-26

Update: I have now added git-http-backend into this mix to allow cloning of these repositories over https. This complicated things quite a bit more than my original posting.

I have recently undergone the enterprise of switching all of my web servers from apache2 to nginx. I don't have anything in particular against apache2, but it uses much more memory and I don't really need most of its features.

This transition went smoothly for the most part, with the exception of converting my web-accessible git interface using gitweb. I found a few guides on the topic but nothing that worked quite the way I wanted it to.

First of all, I have made some alterations to the default gitweb.conf:

# path to git projects (<project>.git)
$projectroot = "/home/git/repositories/";

# directory to use for temp files
$git_temp = "/tmp";

# html text to include at home page
$home_text = "indextext.html";

# file with project list; by default, simply scan the projectroot dir.
$projects_list = "/home/git/projects.list";

# stylesheet to use
@stylesheets = ("static/gitweb.css");

# javascript code for gitweb
$javascript = "static/gitweb.js";

# the 'favicon'
$favicon = "static/eab-favicon.png";

# git-diff-tree(1) options to use for generated patches
@diff_opts = ();

### secret shit not in the docs (angryface)

# enable nicer uris
$feature{pathinfo}{default} = [1];

# root link text
$home_link_str = '';
$site_name = '';

I cannot stand the way gitweb does uris by default, but the "nicer uris" was where most of the headache came from when I was moving to nginx. Here is the nginx configuration I settled on:

server {
  listen 443;

  error_log /var/log/nginx/git.error.log;
  access_log /var/log/nginx/git.access.log;

  # ssl because cox sucks
  ssl on;
  ssl_certificate /etc/nginx/ssl/;
  ssl_certificate_key /etc/nginx/ssl/server.key;

  root /usr/share/gitweb;

  # static repo files for 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;

    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    fastcgi_param SCRIPT_FILENAME   /usr/lib/git-core/git-http-backend;
    fastcgi_param PATH_INFO         $uri;
    fastcgi_param GIT_PROJECT_ROOT  /home/git/repositories;  
    include fastcgi_params;

  # send anything else to gitweb if it's not a real file
  try_files $uri @gitweb;
  location @gitweb {
    fastcgi_pass unix:/var/run/fcgiwrap.socket;
    fastcgi_param SCRIPT_FILENAME   /usr/share/gitweb/gitweb.cgi;
    fastcgi_param PATH_INFO         $uri;
    fastcgi_param GITWEB_CONFIG     /etc/gitweb.conf;
    include fastcgi_params;

Hopefully this comes in handy to someone else trying to do such a setup.