We will describe here how to publish a group of Mercurial repositories on a web server. It will allow us to access it with a traditional web browser. For that we will link the web server to Mercurial with CGI. Once a repository is setup it is very easy to add others.


  • a functioning web server (here we will base on lighttpd for the instructions) see [[linux:debian:webserveur]] for its installation.
  • a classical installation of Mercurial.
  • The hgwebdir.cgi or hgwebdir.fcgi script include with your version of Mercurial. On a Debian install, you can find it in the /usr/share/doc/mercurial/examples/ folder. It is also directly available on Mercurial website: hgwebdir.cgi
  • In the case of use of the fastCGI version of the script (hgwebdir.fcgi) we should also install the flup python module (python-flup pour Debian)

Repository preparation

We will suppose that the repository is in the /var/hg folder. First we create the structure of the repository:

# mkdir -p /var/hg/repos
# chown -R www-data:www-data /var/hg

Then we create the configuration file of the repository /var/hg/hgweb.config which will allow us to take into account the different mercurial repositories that will be in the repos sub-folder:

repos/ = repos/

Then we need to place the hgwebdir.fcgi script (in case of FastCGI use) or hgwebdir.cgi script (in case of CGI use) and to let executable by the web server:

# mkdir /var/hg
# cp hgwebdir.fcgi /var/hg
# chown -R www-data:www-data /var/hg
# chmod +x /var/hg/hgwebdir.fcgi

lighttpd configuration

In a sub-directory of the site

According to lighttpd documentation, we need to edit the /etc/lighttpd/lighttpd.conf configuration file or a file which will be include at lighttpd start up. In Debian you can create a file (for example 50-hg.conf) in the /etc/lighttpd/available-conf/ folder. Then create a symlink to that file in /etc/lighttpd/enable-conf/.

First you need to include the requiered modules:

1  server.modules += ( "mod_cgi" )
2  server.modules += ( "mod_rewrite" )

Second, you have to configure the address rewriting so the access to the sub-directories of hg should use hgwebdir.fcgi :

3  url.rewrite-once = (
4    "^/hg([/?].*)?$" => "/hgwebdir.fcgi$1",
5  )

Finally, passing the correct parameters to the CGI script:

6  $HTTP["url"] =~ "^/hgwebdir.fcgi([/?].*)?$" {
7               server.document-root = "/var/hg/"
8               cgi.assign = ( ".fcgi" => "/usr/bin/python" )
9  }

As a virtual host

In that case, the repositories will be accessible directly at the root of the host through an address like hg.example.com.

First, as before, you need to include the requiered modules:

1  server.modules += ( "mod_cgi" )
2  server.modules += ( "mod_rewrite" )

Second, in that case we will configure that all access to hg.example.com will use the FastCGI script.

3  $HTTP["host"] == "hg.example.com" {
4      server.document-root = "/var/hg/"
5      cgi.assign = ( ".fcgi" => "/usr/bin/python" )
6  }

In that case, the addresses will show the name of the cript to use, that is hgwebdir.fcgi. As before we could can use the rewriting directive to have sexier addresses, so without the name of the script:

7  url.rewrite-once = (
8      "^(/hgwebdir.fcgi/.*)$" => "$1", "^(/.*)$" => "/hgwebdir.fcgi$1"
9  )

In the Mercurial config file (hgweb.config) you should also specify that there is no prefix on the addresses:

baseurl =

Push limitation

The FastCGI/CGI script allow read but also write to the repositories. Therefore to be able to limit the write (push) to only certian person two additionnal modifications are requiered.

First in the configuration file of the mercurial repository itself where you want to put some limitation (.hg/hgrc). In the web section, add the names of the autorised users, or a star (*) to allow everybody:

allow_push = moimeme

Finally in lighttpd configuration in the file where authentication are specified:

$HTTP["querystring"] =~ "cmd=unbundle" {
                auth.require = (   "" => (
                        "method"  => "basic",
                        "realm"   => "Mercuial Repo",
                        "require" => "valid-user"

During a push it may failed with the following error:

ssl required

To allow pushes without SSL activated, just set it in the Mercurial configuration file of the corresponding repository (.hg/hgrc):

push_ssl = false