Another Python/Mercurial/mod_wsgi on CentOS HOWTO – 2/2

In part 1 I covered how to install Python, Mercurial and mod_wsgi. In this article I’ll explain how to publish your repositories.

Configure Apache + mod_wsgi
Load up your apache httpd.conf file into your favourite editor and add the following lines:

LoadModule wsgi_module modules/
AddHandler wsgi-script .wsgi
WSGIPythonHome /opt/python2.7.2

That last line ensures that mod_wsgi knows which Python to invoke.

On my system I’m using named virtual hosts, this is what my Mercurial’s site virtual host configuration looks like:

 ServerName mercurial
 ServerAdmin root@localhost
 DocumentRoot /sites/mercurial/htdocs
 WSGIScriptAlias / /sites/mercurial/htdocs/cgi-bin/hgweb.wsgi

Under your document root create a folder called cgi-bin and create a file in there called hgweb.wsgi.

To verify that mod_wsgi is working I used the trouble-shooting script found on the “Installation Issues” section of the mod_wsgi site. So drop that code into the newly created hgweb.wsgi file and save it:

import sys

def application(environ, start_response):
    status = '200 OK'
    output = 'Hello World!'

    response_headers = [('Content-type', 'text/plain'),
                        ('Content-Length', str(len(output)))]
    start_response(status, response_headers)

    print >> sys.stderr, 'sys.prefix = %s' % repr(sys.prefix)
    print >> sys.stderr, 'sys.path = %s' % repr(sys.path)

    return [output]

When you browse to your site you should see: Hello World! in my browser. So far so good.

Mercurial Configuration
If the above works then replace the contents of hgweb.wsgi with the following:

# An example WSGI for use with mod_wsgi, edit as necessary
# See for more information

# Path to repo or hgweb config to serve (see 'hg help hgweb')
config = "/sites/mercurial/htdocs/cgi-bin/hgweb.config"

# Uncomment and adjust if Mercurial is not installed system-wide:
#import sys; sys.path.insert(0, "/path/to/python/lib")

# Uncomment to send python tracebacks to the browser if an error occurs:
#import cgitb; cgitb.enable()

# enable demandloading to reduce startup time
from mercurial import demandimport; demandimport.enable()

from mercurial.hgweb import hgweb
application = hgweb(config)

You can find this file in the Mercurial source in the contrib folder. If you’ve followed my instructions to the word

Next create a new file in the cgi-bin folder called hgweb.config and add the following:

/ = /sites/mercurial/htdocs/repos/**
allow_push = *
push_ssl = false

Create a folder for your repositories under your document root and initialise a new repository:

mkdir repos
cd repos
hg init testrepo

You should now be able open the Mercurial repository browser by opening:

You also need to ensure that your web server’s user can read and write to your repositories. On a default apache install on CentOS this should look like:

chown -R apache:apache /sites/mercurial/htdocs/repos
chmod -R g+rw /sites/mercurial/htdocs/repos
chmod g+x /sites/mercurial/htdocs/repos

You also need to make each repository folder and it’s .hg folder executable as well:

chmod g+x /sites/mercurial/htdocs/repos/testrepo
chmod g+x /sites/mercurial/htdocs/repos/testrepo/.hg

For more info see: Mercurial – 8. Troubleshooting

To test your Mercurial server go to a different machine and do:

E:\>md hg_test

E:\>cd hg_test

E:\hg_test>hg clone
destination directory: testrepo
no changes found
updating to branch default
resolving manifests
0 files updated, 0 files merged, 0 files removed, 0 files unresolved

E:\hg_test>cd testrepo

E:\hg_test\testrepo>copy con test.txt
Hello World!
        1 file(s) copied.

E:\hg_test\testrepo>hg add test.txt
adding test.txt

E:\hg_test\testrepo>hg commit test.txt -m "Test commit"
committed changeset 0:1904a8ab9a97

E:\hg_test\testrepo>hg push
pushing to
searching for changes
1 changesets found
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files


If we browse to our repository we can see the file we just pushed:

If you follow all of the steps exactly you should end up with a basic but working Mercurial server that you can use to push and pull changesets to.

Obviously you should secure this server if it’s public facing (mine is secured with a simple .htaccess/.htpassword affair for now).

There were a number of sites and documents online that helped me to get this far, these included:

The following Mercurial articles also helped:

This entry was posted in CentOS, Mercurial, Python. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *