Sunday, 17 June 2012

Mercurial, Apache and mod_wsgi


In a previous post, you might have read that I was given a mission to set up a Mercurial code repository for users within a private network, to be accessed via passwords. What this meant was, use Apache web server to serve up a Mercurial repository as a live URL, with basic HTTP authentication via passwords.

Normally I access things stored in Mercurial through ssh protocol, not HTTP, so this was something I hadn't tried in a long time. My memory doesn't stretch back more than six months! So, I wrote down what I had to do to achieve this. I needed to make Mercurial, Apache, mod_wsgi and Python play nicely together.

I thought I would share the things I did to get things going. I'm assuming that you already know something about:
  • Apache HTTP server
  • Linux, the command line and apt for packages
  • Python and WSGI
  • Mercurial version control system (cloning)

If you're interested, the server was running slightly older versions of things: Ubuntu 10.04 and Python 2.6x. That's why I went with the slightly old mod_wsgi for Apache. Even though I did this on Ubuntu, I dare say these instructions would be almost identical for someone using Linux Mint, Crunchbang or Debian.

Here are the steps to follow, for a project named "booklister"

On the server


Make sure you have copied your project's source files over to the server first,
e.g. by zipping them and using scp

Install Apache and Mercurial
apt-get install apache2 mercurial

Install the mod_wsgi interface for Python
apt-get install libapache2-mod-wsgi

Restart Apache
/etc/init.d/apache2 restart
Install the Python module for Mercurial
pip install mercurial
Create an "hgusers" group for all users who will be working with the repository
groupadd hgusers

Add users into the group, using this format:
usermod -a -G GROUPNAME USERNAME

usermod -a -G hgusers scott
usermod -a -G hgusers anotheruser
You can view the users in the new group:
cat /etc/group

Setup password access for Mercurial via Apache: create user passwords for Apache authentication using the htpasswd utility

htpasswd -cb /etc/apache2/hgpasswd scott scottspassword
htpasswd -b /etc/apache2/hgpasswd anotheruser anotherpassword

Create a directory which will hold the Mercurial repositories.
Set permissions on it for the Apache user and the hgusers group
cd /var/lib
mkdir hg_repos
chown -R www-data:hgusers hg_repos
chmod -R g+rwx hg_repos

Initialise a Mercurial repository, and copy source project files into it. Add them all into version control.

hg init booklister
cd booklister
cp -r /home/scott/temp/booklister/* .
hg add
Create an hgrc file (for Mercurial) in the repository's .hg directory
vim .hg/hgrc

[ui]
username = "scott@mycompany.com"

[trusted]
groups = hgusers
users = scott, anotheruser

[web]
allow_read = scott, anotheruser
allow_push = scott, anotheruser
allow_archive = gz, zip, bz2
push_ssl=False
Create an hgweb.wsgi file (for mod_wsgi) in the repository directory
vim hgweb.wsgi

#!/usr/bin/env python


""" File for Mercurial, Apache and mod_wsgi http access.
Enable demandloading to reduce startup time.
"""


from mercurial import demandimport
from mercurial.hgweb import hgweb


# Path to repo or hgweb config to serve (see 'hg help hgweb')
config = "/var/lib/hg_repos/booklister"
demandimport.enable()
application = hgweb(config)

Make an initial commit for the new files, with a comment

hg commit -m "First commit"
Correct permissions on the repository files that may be new or changed

cd /var/lib/hg_repos
chown -R www-data:hgusers booklister
chmod -R g+rwx booklister
Edit the Apache config file (or a virtual host file). Add Directory and Location blocks.

vim /etc/apache2/apache2.conf

WSGIScriptAlias /booklister /var/lib/hg_repos/booklister/hgweb.wsgi
WSGIDaemonProcess booklister user=www-data group=hgusers threads=1 processes=10
<Directory /var/lib/hg_repos/booklister>
  Options ExecCGI FollowSymlinks
  AddHandler wsgi-script .wsgi
  AllowOverride None
  Order deny,allow
  deny from all
  allow from vvv.ww.xxx.y/zz
</Directory>

ScriptAlias /booklister "/var/lib/hg_repos/booklister/hgweb.wsgi"
<Location /booklister>
  AuthType Basic
  AuthUserFile /etc/apache2/hgpasswd
  AuthName "Book Lister project repo"
  Require valid-user
</Location>

Restart Apache
/etc/init.d/apache2 restart


Locally


Clone the remote repository in a desired location. You'll now have a local copy!

cd /home/scott/ws/py
hg clone http://myserver/booklister

-Enter user name and password

scott
scottspassword

Create a local rc file for Mercurial. You can do this in your home ~ directory,
or in the clone project's folder. I usually put mine in the project's folder.

cd booklister
vim .hg/hgrc

[ui]
username = Scott Davies <scott@mycompany.com>
password = scottspassword

[paths]
default = http://myserver://booklister

Try making a change to file, then try to push the change to the repository

hg commit -m "Test change"
hg push

pushing to http://myserver//booklister
http authorization required
realm: Book Lister project repo
searching for changes
remote: adding changesets
remote: adding manifests
remote: adding file changes
remote: added 1 changesets with 1 changes to 1 files

1 comment: