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

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:

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:

/ = /var/hg/**

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;
    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;

The directive limit_except in Nginx does not 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.