Mercurial, Apache and mod_wsgi
I serve my Subversion repositories using Apache with mod_dav and mod_dav_svn. This is useful because it frees me from either having to run a separate Subversion-specific server which duplicates existing Apache functionality, or SSH which obviously requires shell access for checking out as well as committing code. It was logical to provide a similar setup for my more recently adopted Mercurial repositories, so as promised to Ryan, here's a brief run through of how I did it.
The following Mercurial wiki pages were my main source of information and were useful, if disjointed and partially redundant: Publishing Mercurial Repositories, Publishing Repositories with hgwebdir.cgi, Serving Mercurial repositories with Apache and mod_wsgi.
This is written with Mercurial 1.4.1 and Apache 2.2.14 in mind.
Serving hgwebdir
The recommended method of serving multiple Mercurial repositories is with hgwebdir.cgi. Since the underlying Python application called by this script employs WSGI, it's much more sensible to serve it with mod_wsgi than with mod_python, CGI or FastCGI. Both hgwebdir.cgi and its mod_wsgi sister hgwebdir.wsgi are included in the Mercurial package and can be found in /usr/share/doc/mercurial-*/ or /usr/share/doc/mercurial-*/contrib .
Configuring hgwebdir
Copy hgwebdir.wsgi to wherever you'll be serving it from, for example /var/www/hg.example.com/cgi-bin/ and make it readable and executable by your Apache user. At the bottom of the file you'll need to provide the full path to a config file which you'll create in the next step, so that's /var/www/hg.example.com/cgi-bin/hgweb.config . Now create hgweb.config, remembering to chown, and specify the path to your repositories as below.
[paths] / = /var/hg/**
On the left is what you'll have to append to http://hg.example.com to access the repository listing, in this case it's simply / . On the right is the filesystem path to the directory containing your repositories. The double asterisk allows recursion into directories that are not themselves repositories, so you can have for example /var/hg/bobs-repos/repo1, /var/hg/bobs-repos/repo2, /var/hg/daves-repos/repo1 et cetera.
Configuring mod_wsgi
There's nothing special to be done as regards server-wide setup for mod_wsgi, so now you can take your favourite template VirtualHost block, and insert the relevant lines as below. I choose to use mod_wsgi's daemon mode, in which each WSGI application runs as a separate process, though embedded mode is also perfectly feasible for this application. The hg.example.com tags in WSGIDaemonProcess and WSGIProcessGroup are merely descriptive and need not be related to the domain name. Again your choice of authentication method, if any, is obviously non-critical.
<VirtualHost *:80>
ServerName hg.example.com
DocumentRoot /var/www/hg.example.com/htdocs
WSGIScriptAlias / /var/www/hg.example.com/cgi-bin/hgwebdir.wsgi
WSGIDaemonProcess hg.example.com user=apache group=apache processes=2 threads=15
WSGIProcessGroup hg.example.com
<Directory /var/www/hg.example.com/cgi-bin>
AuthType basic
AuthBasicProvider ldap
AuthName "Mercurial Repositories"
AuthLDAPURL ldap://localhost:389/ou=People,dc=example,dc=com?uid?sub?(objectClass=posixAccount)
Require valid-user
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Configuring repositories
The behaviour of individual repositories is set in /var/hg/reponame/.hg/hgrc . You may control push rights of users either at this point, or in the HTML authentication, using <LimitExcept> if necessary as outlined in the first wiki link.
[web] name = reponame description = Bob's magic Hg repo contact = bob@example.com # force SSL for pushes push_ssl = false # users who may push (comma separated) allow_push = * # users who may not push #deny_push = dave allow_archive = gz zip bz2
As for the repository permissions, the wiki recommends giving the Apache group permissions on the directories. Mercurial users are members of the Apache group to facilitate creation of new repositories without recourse to sudo. It would be much more elegant to keep repositories owned by their creator's user and group, and grant Apache permissions on them using extended POSIX access control lists, but that will be the subject of a separate post. Permissions should be set as follows:
chgrp -R apache /var/hg/reponame chmod -R g+rw /var/hg/reponame chmod g+x /var/hg/reponame chmod g+x /var/hg/reponame/.hg
Finished!
After restarting Apache, you should able to point your browser to http://hg.example.com/ and see your repositories listed. Mission accomplished.