Running Mercurial with FastCGI in nginx

logo-droplets-200 Mercurial is a so called DRCS (Distributed Revision Control System). I have been using Subversion for a couple of years, both at work and for my own projects. Now I thought it was about time to try something different.

But first, why do I want to switch from SVN to Mercurial? Basically the most appealing argument for me was the fact, that with Mercurial I am able to work offline with my repository. Besides that, I always had issues with the way SVN was handling tags and branches. Especially merging changes from a branch back into the trunk was always a pain. I did not need to use that functionality often but when I did, I always ended up doing it twice, because I could not remember which way to do it right.

So, in this article I will describe my setup of Mercurial served via FastCGI behind the nginx webserver. The approach is similar to the integration of PHP into nginx. You need the spawn-fcgi tool from the lighttpd distribution. The following steps should work on a recent Debian or Ubuntu distribution.

The first step is to install Mercurial and some necessary libraries to create the fcgi-wrapper for Mercurial:

aptitude install mercurial python-flup

Now you can already start defining your Mercurial repositories. Here are some steps to create a small example repository:

cd /tmp
hg init hgtest
cd hgtest
echo "Hello world." > readme.txt
hg add readme.txt
hg commit -m "Initial commit"

You now have a Mercurial repository with a single file. The command hg log should show you a single changeset with our commit comment.

Now, let’s start configuring nginx to integrate Mercurial. We will use FastCGI talk connect Mercurial to nginx. User authentication will be done via nginx. It is a good idea to use HTTPS for communication with Mercurial, but we will focus on a standard HTTP setup.

Let’s setup a virtual host for Mercurial. Open /etc/nginx/sites-available/your_domain_name and add the following server definition:

server {
        listen 80;
        server_name YOUR_MERCURIAL_DOMAIN;
        location / {
                auth_basic "Secure Login";
                auth_basic_user_file /tmp/mercurial_users;
                fastcgi_param SCRIPT_FILENAME /tmp$fastcgi_script_name;
                fastcgi_param PATH_INFO $uri;
                fastcgi_param REMOTE_USER $remote_user;
                include fastcgi_params;

The above settings will setup a new virtual host, where all traffic is redirected to the Mercurial FastCGI wrapper. It is important that you forward the PATH_INFO and REMOTE_USER variables. Mercurial will not work correctly without these.

Now reload the nginx configuration:

/etc/init.d/nginx reload

And create the password file:

htpasswd -c /tmp/mercurial_users MYLOGIN

Mercurial uses a central configuration file. In this file we can specify locations for our mercurial repositories. The following file will enable all mercurial repositories found in the /tmp directory. It also changes the theme to gitweb which is a bit clearer than the default theme. Create the file /tmp/hgweb.config with the following contents:

/tmp = /tmp

style = gitweb
baseurl =

Mercurial uses a second configuration file for each repository where you may specify details about the repository and security settings like who may push changes into the repository. The configuration should be placed into the file /tmp/hgtest/.hg/hgrc and could look like this:

contact = YOUR NAME
style = gitweb
push_ssl = false
allow_archive = bz2 gz zip
allow_push = LOGIN_NAME

Now we need to grab the following script from the Mercurial repository and place it into the /tmp directory: Now edit this file and replace the line WSGIServer(hgwebdir('hgweb.config')).run() with WSGIServer(hgwebdir('/tmp/hgweb.config')).run().

The last step is to set the correct filesystem rights for your repository:

chown -R www-data.www-data /tmp/hgtest

That’s it. Now we can start the FastCGI process via:

spawn-fcgi -a -p 9001 -u www-data -g www-data -f /tmp/hgwebdir.fcgi -P /var/run/ -C 1

It makes sense to write the above line into /etc/rc.local so that it will start up automatically when you reboot the server.

Further information about configuring your Mercurial server can be found in the Mercurial Wiki.

Leave a Reply