Making nginx serve git-http-backend and gitweb on the same URL

No Comments

After setting up gitweb on http://git.stuge.se/ I tried to configure it so that links would be as pretty as possible both to the gitweb front page which lists all repositories and into the repositories themselves. Links generated by gitweb itself start with http://git.stuge.se/?p=repo.git, and that is how I left things at first, but the ?p= part is really just ugly noise that I always wanted to get rid of.

I eventually researched which actual paths git-http-backend requires for cloning a repository (read-only!) from a http:// URL, and arrived on the following piece of nginx configuration to make it work.

The result is that a pretty http://git.stuge.se/repo.git URL can be used both for git clone and as a landing page for humans using a browser. All links in gitweb still have the ?p= because gitweb would need some fairly deep code changes to recognize which repository is being accessed without using such an URL parameter. Maybe some day in the future. ;)

Here's the nginx.conf server block:

server {
  server_name git.stuge.se git.libusb.org git.libssh2.org git.imcom.im;
  root /var/lib/git;

  location ^~ /static/ { alias /usr/share/gitweb/static/; }

  location ~ ^/[^/]*\.git/(git-upload-pack|HEAD|info|objects|refs) {
    alias /usr/libexec/git-core/git-http-backend;
    include /etc/nginx/fastcgi_params;
    fastcgi_param GIT_PROJECT_ROOT /var/lib/git;
    fastcgi_pass unix:/var/run/spawn-fcgi/git-http;
  }

  location / {
    alias /usr/share/gitweb/gitweb.cgi;
    include /etc/nginx/fastcgi_params;
    fastcgi_pass unix:/var/run/spawn-fcgi/gitweb;
  }
}

The FastCGI sockets are created by long-running spawn-fcgi processes which in turn use fcgiwrap to make CGI programs look and feel like FastCGI. For git-http-backend:

spawn-fcgi -n -s /var/run/spawn-fcgi/git-http -u gitweb -U nginx -d /var/lib/git -f /usr/bin/fcgiwrap

and for gitweb.cgi:

spawn-fcgi -n -s /var/run/spawn-fcgi/gitweb -u gitweb -U nginx -d /var/lib/git -f /usr/bin/fcgiwrap

For completeness, this is what fastcgi_params looks like:

fastcgi_param  QUERY_STRING       $query_string;
fastcgi_param  REQUEST_METHOD     $request_method;
fastcgi_param  CONTENT_TYPE       $content_type;
fastcgi_param  CONTENT_LENGTH     $content_length;

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;
fastcgi_param  REQUEST_URI        $request_uri;
fastcgi_param  DOCUMENT_URI       $document_uri;
fastcgi_param  DOCUMENT_ROOT      $document_root;
fastcgi_param  SERVER_PROTOCOL    $server_protocol;
fastcgi_param  HTTPS              $https if_not_empty;

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;
fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version;

fastcgi_param  REMOTE_ADDR        $remote_addr;
fastcgi_param  REMOTE_PORT        $remote_port;
fastcgi_param  SERVER_ADDR        $server_addr;
fastcgi_param  SERVER_PORT        $server_port;
fastcgi_param  SERVER_NAME        $server_name;

fastcgi_param  REDIRECT_STATUS    200;

Hopefully this can help you also have pretty repository URLs!