Zach Burlingame
Programming, Computers, and Other Notes on Technology

Installing Mercurial and Hosting Repositories with CentOS

In the previous post I discussed some things to consider when publishing mercurial repositories. Here I explain the steps I took to setup and configure Mercurial repository publishing via SSH and HTTPS on CentOS 5.5 x64.

Prerequisites

These are the prereqs for my setup. Most of these instructions will probably work on other distros and web servers, but the exact commands and details will vary.

  • CentOS 5.5
  • Apache 2.x (Installed and Configured)
  • root or sudo access on the server
  • Internet Connection during installation (yes, some of us do development on offline networks)

Download and Install Packages

The mercurial packages that are available directly out of the CentOS repositories and RPMForge for CentOS 5.5 were too old for my liking. I downloaded the latest RPMs (at the time of writing) directly. Update 2011/03/30: Mercurial 1.8.x is now in RPMForge for EL5 so you can get it directly via yum.

sudo yum install python-docutils python-setuptools mercurial mercurial-hgk mercurial-ssh
I ran into an dependency resolution issue because I have the EPEL repo enabled with a higher priority than RPMForge. I added the following line to the [epel] entry in /etc/yum.repos.d/epel.repo to force yum to look for mercurial elsewhere so it pulled from RPMForge.
exclude=mercurial,mercurial-hgk,mercurial-ssh

Create an hg Group

I find it useful to create a group for all of the version control users on the server because I want to support both HTTPS and SSH access. If you are using HTTPS access only, then you don’t need a group here since it will all be done via apache. I used hg here but you could use anything you want like vcs or versioncontrol.

sudo groupadd hg
# Add all committers to the hg group using usermod

Create and Configure a Repo

Note that I go through a few extra hoops here to allow multiple-committers since I want to support both SSH and HTTPS access.

# Create your new Hg repo (or copy the existing one) in /srv/hg
sudo hg init /srv/hg/

# Make the repo writable by the group for a multiple-committers environment
cd /srv/hg/
sudo chgrp hg .hg .hg/* .hg/store/*
sudo chmod g+w .hg .hg/* .hg/store/*
sudo chmod g+s .hg .hg/* .hg/store/data

# Give ownership of Hg repos to the apache user
sudo chown -R apache /srv/hg/

# Setup your .hgignore file to handle files you don't want under version control

# Add your project files to the repo
hg add

# Commit your project
hg commit

Setup HgWeb

There is great documentation on how to do this on the Mercurial Wiki but here are the steps I used.

# Setup Hgweb for HTTP access using mod_python
sudo mkdir /etc/hgweb
sudo mkdir /var/hg

sudo vim /var/hg/hgwebdir.py
########## BEGIN COPY BELOW THIS LINE ###########
#!/usr/bin/env python
#
import cgitb
cgitb.enable()

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

def make_web_app():
    return hgwebdir("/etc/hgweb/hgwebdir.conf")

def start(environ, start_response):
    toto = wsgiapplication(make_web_app)
    return toto (environ, start_response)
############ END COPY ABOVE THIS LINE ############

sudo vim /etc/hgweb/hgwebdir.conf
######### COPY BELOW THIS LINE #############
[collections]
/srv/hg = /srv/hg

[web]
style = gitweb
allow_archive = bz2 gz zip
contact = Your Name, your.email@address.com
allow_push = *
push_ssl = true
######## END COPY ABOVE THIS LINE ###########

Setup modpython_gateway

We need a dynamic landing page to handle access to the collection of all repos available on the box rather. This way we don’t have to setup a static landing page for each and every repo we publish. I’m using the ever popular modpython_gateway script for this.

wget http://www.aminus.net/browser/modpython_gateway.py?format=raw
sudo mv modpython_gateway.py\?format\=raw /var/hg/modpython_gateway.py

# IMPORTANT! Only use the -c flag for the FIRST person you add, drop it for every add after that
sudo htdigest -c /etc/hgweb/users.htdigest "Zach's Mercurial Repository" burly

sudo vim /etc/httpd/conf.d/hgweb.conf
######### BEGIN COPY BELOW THIS LINE ########

        PythonPath "sys.path + ['/var/hg']"
        SetHandler mod_python
        PythonHandler modpython_gateway::handler
        PythonOption wsgi.application hgwebdir::start

        AuthType Digest
        AuthName "Zach's Mercurial Repository"
        AuthDigestProvider file
        AuthUserFile "/etc/hgweb/users.htdigest"

        Require valid-user

        # Redirect all non-SSL traffic automagically
        RewriteEngine On
        RewriteCond %{HTTPS} off
        RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}

####### END COPY ABOVE THIS LINE ##########

Configure Apache

We need to enable WSGI handling in apache and that we have all the right file permissions. If you don’t have a CA cert you’ll need to setup one up if you want to use SSL. Here is how to do that on CentOS.

sudo vim /etc/httpd/conf/httpd.conf
# Add the Following Lines in their Respective Locations in the Conf
####### BEGIN COPY BELOW THIS LINE ########
LoadModule wsgi_module modules/mod_wsgi.so
AddHandler wsgi-script .wsgi
####### END COPY ABOVE THIS LINE #########

sudo chown -R root.root /etc/hgweb
sudo chown apache.apache /etc/hgweb/users.htdigest
sudo chmod 400 /etc/hgweb/users.htdigest
sudo chown -R apache.apache /var/hg

sudo service httpd restart

Use your Repo!

You should now be able to view your repositories by pointing your browser at http://yermachinenameorip/hg and you should be prompted for the username and password created in your htdigest file from earlier (i.e. not your shell account credentials). Note that due to the re-write rule in our hgweb.conf file, you should automatically be redirected to the SSL version of the site.

You should now be able to clone your repo via https and your htdigest credentials via:

hg clone https://@yermachinenameorip/hg/reponame

or via SSH and your shell account credentials via:

hg clone ssh://@yermachinenameorip/srv/hg/reponame

Maintenance

#--------------------------
# Create a new project
#--------------------------
hg init /srv/hg/<reponame>

# Make the repo writable by the group for a multiple-committers environment
cd /srv/hg/<reponame>
sudo chgrp hg .hg .hg/* .hg/store/*
sudo chmod g+w .hg .hg/* .hg/store/*
sudo chmod g+s .hg .hg/* .hg/store/data

# Give ownership of Hg  repos to the apache user
sudo chown -R apache /srv/hg/<reponame>

hg add
hg commit

#--------------------------
# Add a new user
#--------------------------
useradd  -G hg
passwd

# Set the htaccess password for the user
htpasswd /etc/hgweb/users.htdigest

Additional Resources

2 Responses to “Installing Mercurial and Hosting Repositories with CentOS”

  • Mauriat says:

    Just thought I should point out, if you install
    # yum install mercurial-hgk mercurial-ssh
    from RPMForge, you get the same versions you have listed above.

    Otherwise, your notes seem well written and I do plan to test them out.

    • ZachB says:

      Ahh, right you are Mauriat! When I originally drafted this out I was getting 1.7.x but I had already upgraded to 1.8.x on my client machines. I’ve updated the guide accordingly. Thank you!

  • Leave a Reply to Mauriat Cancel reply

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

    *