HOWTO setup the Mercurial with Nginx in CentOS 4

As my VPS provider Advantagecom Networks gracefully acknowledged the life-time promotion I enrolled in one year ago, I decided to settle in this ISP. Which also means that I am stuck to the current configuration: python-2.3.4 in CentOS 4.

Unlike Gentoo, there is no shortcut to upgrade CentOS 4 to CentOS 5 seamlessly. Some adventurous pilots tried and failed miserably, also the customer service disregarded this approach. I wish I could reinstall the OS in SSH session. So we fallback the plan B to update the essential components only.

Update the python

wget http://www.python.org/ftp/python/2.6.2/Python-2.6.2.tar.bz2
tar xvfj Python-2.6.2.tar.bz2
cd Python-2.6.2
./configure --prefix=/opt
make && sudo make install

Update the setuptools for python-2.6

Temporarily override the PATH to use python-2.6:

wget http://pypi.python.org/packages/2.6/s/setuptools/setuptools-0.6c9-py2.6.egg#md5=ca37b1ff16fa2ede6e19383e7b59245a
PATH=/opt/python/bin:$PATH sudo sh build/setuptools-0.6c9-py2.6.egg

By default, easy_install will be installed into /opt/python/bin.

Install Mercurial and flup

sudo /opt/python/bin/easy_install mercurial
sudo /opt/python/bin/easy_install flup

Setup the Mercurial repository

# Setup the user privilege
sudo /usr/sbin/groupadd hg
sudo /usr/sbin/useradd -g hg -s /bin/false hg
sudo mkdir /var/hg
sudo chown hg:hg /var/hg
sudo chmod g+w /var/hg
# Add myself to hg group
sudo /usr/sbin/usermod -G hg bookstack
hg init /var/hg/bloggo

Serve Mercurial via flup

Copy the fastcgi script hgwebdir.fcgi from /usr/share/doc/mercurial-1.3.1/contrib/, and configure the hgweb.config:

[paths]
/ = /var/hg/**

[web]
style = monoblue
allow\_push = *
push\_ssl = false

Spawn the fastcgi script using this script.

Note: the PATH environment variable needs to be overridden by /opt/python/bin

Install Nginx

Just follow this HOWTO.

Now we need to setup the Nginx to expose the Mercurial repository in nginx.conf:

# HG
server {
    listen 80;
    server_name dev.kunxi.org;
    root /var/web/$host;
    access_log logs/$host.access.log main;
    error_log logs/$host.error.log;

    location /hg/ {
        fastcgi_split_path_info ^(/hg)(/.*)$;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        include fastcgi_params;
        limit_except GET HEAD {
            deny all;
        }
        fastcgi_pass 127.0.0.1:9003;
    }
}

The directive limit_except in Nginx seem not to work as expected. If we add auth_basic in limit_except block, Nginx will ask for the credential first, then tries to server the static content in /hg/project_name instead of passing the request to the underlying fastcgi. I encountered the similar problem in MoinMoin setup, so I just deny all the POST operations, and use SSH instead. This is not the perfect solution for sure, but it works fine for personal source depot.