Monday, May 31, 2010

Mercurial Setup Guide

1 Introduction

Repositories are useful in managing software projects, mainly because they provide a means of source code collaboration. There are various forms of repositories, though this post will talk about Mercurial, which is a distributed version control system. Mercurial is typically used in situations where a software project is managed in a team, with various users developing on the same code base. A source control management system can be internal which means that it is only available on the local machine or local area network. The internal solution is ideal for personal projects work, though for more open work an external solution is necessary to allow for accessibility from any Internet connection. This guide will detail the process of setting up an external solution since it requires much more work then an internal set up. To do this Mercurial will be set up behind an Apache HTTP Server that is configured to provide external access.

2 System Setup

Due to the popularity of Ubuntu, and personal usage of Arch Linux both commands will be outlined when needed. The commands will begin with either ubuntu# or arch# for the specific distribution, otherwise just a # will be used when both are applicable. In addition, most Linux distributions are fairly similar which means that the installations of packages will be the same for the majority. The release for Arch Linux is 2009.08, and the release for Ubuntu is 10.04, both on 32-bit architecture.

For Ubuntu, just perform the following to acquire and setup Apache, PHP and MySQL. Then skip to section 3.
ubuntu# sudo apt-get install lamp-server^

2.1 Install Apache

Install the Apache package.
arch# sudo pacman -S apache

Apache should work right now, a quick test using the following command should start Apache.
arch# sudo /etc/rc.d/httpd start

To confirm it works browse to http://localhost/. Then close down Apache for now.
arch# sudo /etc/rc.d/httpd stop

Make the Apache service starts on boot, the httpd deamon will be added to the /etc/rc.conf file.
DEAMONS=(... httpd ...)

2.2 Install PHP

Install the required PHP packages.
arch# sudo pacman -S php php-apache

Add the following to the /etc/httpd/conf/httpd.conf file at the end of the LoadModule list.
LoadModule php5_module modules/

Add the following to the /etc/httpd/conf/httpd.conf file at the end of it.
Include conf/extra/php5_module.conf

Change the following line in the /etc/httpd/conf/httpd.conf file to include the bold word.
Options Indexes FollowSymLinks Includes

To test that PHP is operational first make a test file /srv/http/test.php with the following text.
<? php phpinfo(); ?>

Restart/start Apache back up.
arch# sudo /etc/rc.d/httpd start

To confirm it works browse to http://localhost/test.php and PHP information should be visible.

3 Mercurial Repositories

This section is dedicated to making Mercurial repositories accessible externally from the server. The first thing is to first install the Mercurial packages.
ubuntu# sudo apt-get install mercurial
arch# sudo pacman -S mercurial

3.1 Create Folder for Mercurial Repositories

A directory that is not located directly in the web server needs to be created to hold just the repositories (done so that repositories are not exposed). For me Redmine is being used, so ideally the repositories can be placed in there. The following directory needs to be created:
# sudo mkdir /srv/redmine/extra/hg

3.2 Create Folder for Mercurial Scripts

A directory in the web server folder needs to be created to hold the CGI scripts to allow mercurial to be accessible via the web server. The following directory needs to be created:
arch# sudo mkdir /srv/http/cgi-bin
ubuntu# sudo mkdir /var/www/cgi-bin

3.3 Create hgweb.config File

Within the previously created folder cgi-bin, the file hgweb.config needs to be created. This file directs where the Mercurial repositories are located. It needs to be created with the following contents:
 /srv/redmine/extra/hg/ = /srv/redmine/extra/hg/
The created file is the bare-minimum required for this set up to function. The paths should be set correctly to the system's file structure. In the case where a more fine-tuned file is needed, please consult the mercurial support page.

3.4 Create hgwebdir.cgi File

Within the previously created folder cgi-bin, the file hgwebdir.cgi needs to be created. This file is used to enable interaction from the external connection on the Mercurial repositories. It needs to be created with the following contents:
#!/usr/bin/env python
 from mercurial import demandimport; demandimport.enable()

 import cgitb

 import os
 os.environ["HGENCODING"] = "UTF-8"

 from mercurial.hgweb.hgwebdir_mod import hgwebdir
 import mercurial.hgweb.wsgicgi as wsgicgi

 application = hgwebdir('hgweb.config')
The created file is the bare-minimum required for this set up to function. In the case where a more fine-tuned file is needed, please consult the Mercurial support page.

3.5 Configure Permissions

The web server need to have executable permissions on the hgwebdir.cgi file to allow for proper functionality. This can be set by being in the correct directory and executing the following command in terminal:
# sudo chmod a+x /path/to/hgwebdir.cgi

3.6 Configure Apache Access to the Repositories

A file is needed to configure Apache to direct certain HTTP requests to act towards the mercurial repositories. This is done by editing/adding the following to the httpd.conf, the file is located at:
arch# /etc/httpd/conf/httpd.conf
ubuntu# /etc/apache2/httpd.conf

The following contents is what should be included in the file (note the paths need to be configured according to the system):
ScriptAliasMatch        ^/hg(.*)        /path/to/cgi-bin/hgwebdir.cgi$1

<Directory /path/to/cgi-bin/>
   Options ExecCGI FollowSymLinks
   AllowOverride None

<Location /hg>
  AuthType Digest
  AuthName "mercurial"
  AuthDigestProvider file
  AuthUserFile /srv/redmine/extra/hg/hgusers
  Require valid-user
The idea is that for security reasons the authentication type used will be digest and it will only transmit the MD5 hash of the passwords. The authentication name must be consistent with the generation of the password(the realm), and acts as an additional salt value (pick what ever you will remember, since you will need it for every user you will create). The authentication file will be located beside the repositories and in this example is called hgusers. This file needs to be created and managed using the htdigest command (a script to simplify this is attached to this guide). This configuration also will only allow for the repositories to be accessed if the user is authenticated. For additional configurations please refer to the Mercurial website's instructions.

In addition, due to the use of the digest authentication method Apache requires the appropriate modules. For Arch Linux the modules should already be enabled by default, if not by chance you just need to enable the following modules:

In Ubuntu that module must be moved from the /etc/apache2/mods-available/ to /etc/apache2/mods-enabled/

4 Services Available

There are now a few services available on this server:
  • Functioning Apache web server
  • PHP and MySQL enabled on the web server
  • Protected Mercurial repositories available externally
With these services it become possible to host a website to indicate the location of the Mercurial repositories or possibly to a different tool (such as Redmine). MySQL is a useful service to have available regardless since there are various applications out there that can benefit from a standard database such as MySQL.

Mercurial now exists on the system and so users are able to perform the basic Mercurial functions. Cloning from any Mercurial repository, as well as being able to start local repositories are now possible. In addition there is always the possible of creating an hosting externally accessible repositories such as how this guide as instructed.

5 Conclusion

By the end of this guide Mercurial should be completely set up along with Apache and PHP. Repositories are externally available and a greater understanding on how to manage it should have been acquired. If in doubt there is plenty of resources available online. There is also the script that I made to help with user and repository management (I will post about this script eventually).

5.1 Key Notes

For the remote repositories to automatically update (using the hooks) the owner of the repository must be what runs the web service. In most cases this is the www-data user, if ever in doubt you can always use these commands to reset the owner and modes.
# sudo chown -R www-data /srv/redmine/extra/hg/
# sudo chmod -R 755 /srv/redmine/extra/hg/

Additionally, a typical ./project/.hg/hgrc configuration would looks like:
default = /srv/redmine/extra/hg/project/

allow_push = user
contact = user
description = Fill me out (in ./project/.hg/hgrc)
push_ssl = false
style = gitweb

users = *
groups = *

changegroup = hg update

These settings are used to allow users (which have to be authenticated using the hgusers file) to push back to the externally located repository. The reasoning for the hook section is to have the external repository to update when it receives a change set from a user. The trusted section is used to ensure that regardless of the users and groups using the repository (locally) that the pushes will still carry through. The rest of these settings can be found in the Mercurial documentation.

1 comment:

  1. I have added a referrences to this article and few more information here: "Setup of Mercurial server with cPanel – the easy way"