Mercurial through nginx and fastcgi

August 3, 2010

I'm changing from using Apache for web serving to Nginx, mainly because my virtual machine is short on memory. This post covers how to host a mercurial repository through Nginx, and follows on from the Apache version at http://drumcoder.co.uk/blog/2010/jun/10/mercurial-repository-apache-fedora-11/. You need the same hgweb.config file in /var/hg/cgi-bin as defined in the Apache instructions.

Install spawn-fcgi

The first step is to install spawn-fcgi.

# wget "http://www.lighttpd.net/download/spawn-fcgi-1.6.3.tar.gz"
# tar -xvf spawn-fcgi-1.6.3.tar.gz
# cd spawn-fcgi-1.6.3
# ./configure
# make all
# make install

Install flup

Next we need to install flup, which contains some python utilities for WSGI.

# apt-get install python-flup

Create CGI File

Create a new file at /var/hg/cgi-bin/hgweb.cgi, and give it execute privileges for the web site user (www-data on debian)

#!/usr/bin/env python

import cgitb
from mercurial.hgweb.hgwebdir_mod import hgwebdir
from mercurial.hgweb.request import wsgiapplication
from flup.server.fcgi import WSGIServer

cgitb.enable()

def make_web_app():
    return hgwebdir("/var/hg/cgi-bin/hgweb.config")

WSGIServer(wsgiapplication(make_web_app)).run()

Note that the path here is to the hgweb.config file, details are in the Apache Mercurial tutorial linked to at the top of this entry.

Start spawn-fcgi

The next stage is to start the fcgi server. Here's the command line to do that:

# spawn-fcgi -f /var/hg/cgi-bin/hgweb.cgi -a 127.0.0.1 -p 9085
spawn-fcgi: child spawned successfully: PID: 6467

We'll look at doing this from an init.d script in a future blog post - there's an example in one of the references linked to below.

Configure nginx

We now need to configure a virtual host in nginx to handle the repository.

server {
    listen 80;
    server_name hg.localhost;

    location / {
            fastcgi_pass 127.0.0.1:9085;
            fastcgi_param PATH_INFO $uri;
            fastcgi_param REMOTE_USER $remote_user;
            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_FILENAME /var/hg/cgi-bin/hgweb.cgi;
    }
}

I originally had include fastcgi_params in here as recommended by most of the tutorials I could find, but it doesn't work - it results in the links within the repository not working, and the css being missing. The top level was fine, but once you were inside a repository, the css was lost (the path was incorrect - the project name was in too many times) and links returned error pages.

References