Trying to follow Buckminster Fuller's example in life, one step at a time to bring you brain scrapings for a new millennium.

Setting up Hg on a Windows machine... Part 2

07 Mar 2012 - Nic Ho Chee

I thought I’d look at securing Hg through Abyss, turning on pushing and pulling through security and what it takes to sort out a backup.  I wanted to look at CVS and SVN which I’ll leave for another time.

This post is the second part, to see the first part go here.


Hg supports SSL/HTTPS and defaults to requiring SSL for pushing operations.  You can turn this off however it isn't a good idea, if you require a URL plus username/password to access a site, you really don't want to be transmitting that data in the clear.  Most of the security is going to be handled through Abyss.  You need to create/import a private key and certificate for the site, create passwords for your users and lock-down directory access to the repo dirs.

Creating a Private Key

Creating a Test Certificate

Ideally, you should buy a certificate from a known provider, for the purposes of this post we're going to create a test certificate.  We can still use this, however when browsers open to the site they will complain that the signing authority is not known, and that do you/they still want to trust the site.  In our case this doesn't matter as we're trusting ourselves not to do anything bad like snarf someone's user/pass data :).

Setting Up The Rest of the Security

Setting Up Hg To Use SSL

 We now have an SSL enabled server, so we need to set up Hg to use it.  This is where it gets a little bit interesting, as there isn't a lot of information about using Abyss and Hg together or how the various hg .ini files work together in windows.  The first thing to understand is that there are two main files you will be playing with:

  2. hgweb.config in the cgi-bin directory.

Mercurial has a few variables which can be set in these files and lays them out here for you:

The first thing to do is create a new clone of the repo in c:\temp\workdir.  Notice that we're cloning over HTTPS now:

hg clone https://localhost/cgi-bin/hgwebdir.cgi/CodeRepo/ProjectA/

Hg will now prompt you for a username/password.  If you don't fancy filling in your username/password each time you can insert the lines below in the Mercurial.ini file and it will supply your credentials each time you carry out an hg command.  Please be aware that it's storing your password on your machine in plaintext, someone could easily come and snarf your machine and password so it needs to be physically secure.  You can add multiple prefixes for all the repos you use and separate username/passwords for each one as long as you create a new groupname as below:

testgroupname.prefix = <insert repo ip here>/cgi-bin/hgwebdir.cgi/CodeRepo/ProjectA
testgroupname.username = bobjones
testgroupname.password = bobjones
testgroupname.schemes = https

Previously we added a file, Test1.txt to our repo, now go to the file in the newly cloned ProjectA repo and add a second line, "thisisasecondstring".  Save the file and we'll try pushing this to the repo.

cd C:\temp\workdir\ProjectA
hg status.

Hg status tells you all of your uncommitted files.  It should say something like:

hg status
M Test1.txt.

Commit the change to the local repo.  Committing as below will carry out a silent commit and only show problems if there are any errors in the operation.

hg commit

Now we can push the change back to the main ProjectA repo.

hg push

UH OH!  You won't be able to push the changes, it should say something like "abort: authorization failed".  You need to set up the Hg install on the webserver for pushing data.

C:\temp\workdir\ProjectA>hg push
pushing to https://localhost/cgi-bin/hgwebdir.cgi/CodeRepo/ProjectA
searching for changes
abort: authorization failed

In your Mercurial.ini file add the line below to allow pushing for bobjones

allow_push = bobjones

Now would be a good chance to check what is going to be pushed to the main repo.  You can do this with the "outgoing" key word.  This will show all of the pending changelists which are to be sent up to the main repo as shown below:

C:\temp\workdir\ProjectA>hg outgoing
comparing with https://localhost/cgi-bin/hgwebdir.cgi/CodeRepo/ProjectA
searching for changes
changeset:   1:cc3bdf715940
user:        bobjones <>
date:        Thu Jan 28 23:55:29 2010 +0000

So... push the changelist... using "hg push".  UH OH... you can't.  You'll get another authorization failed message.  You can attempt to get some more information by forcing hg to output some debug data as shown below:

C:\temp\workdir\ProjectA&gt;hg --debug --traceback push<br/>
sending between command
pushing to
sending capabilities command
capabilities: unbundle=HG10GZ,HG10BZ,HG10UN branchmap lookup changegroupsubset
sending heads command
searching for changes
common changesets up to e5795a7af917
sending branchmap command
1 changesets found
list of changesets:
sending unbundle command
sending 345 bytes
Traceback (most recent call last):
File "mercurial\dispatch.pyc", line 46, in _runcatch
File "mercurial\dispatch.pyc", line 454, in _dispatch
File "mercurial\dispatch.pyc", line 324, in runcommand
File "mercurial\dispatch.pyc", line 505, in _runcommand
File "mercurial\dispatch.pyc", line 459, in checkargs
File "mercurial\dispatch.pyc", line 453, in &lt;lambda&gt;
File "mercurial\util.pyc", line 386, in check
File "mercurial\commands.pyc", line 2356, in push
File "mercurial\localrepo.pyc", line 1452, in push
File "mercurial\localrepo.pyc", line 1590, in push_unbundle
File "mercurial\httprepo.pyc", line 228, in unbundle
File "mercurial\httprepo.pyc", line 128, in do_read
File "mercurial\httprepo.pyc", line 83, in do_cmd
Abort: authorization failed
abort: authorization failed

This is where it gets a little annoying... for some reason setting allow_push in your Mercurial.ini file doesn't force Mercurial to turn on pushing.  It looks like a minor bug, but you have to move this line into the hgweb.config file.  Insert the lines below in the hgweb.ini file and you're good to go.

style = foo
allow_push = bobjones

Run "hg push" again and you have committed your first set of changes over SSL and pushed them back to the main repo :).

Backing Up The Repo

We now have changes that we don't want to lose and need to back up the repo.  Its simple, just zip up the repo directory, in this case C:\temp\MercurialTest\ProjectA and if you need to go back to it simply replace the current directory with the unzipped copy and you're away!  You can set up a cron job to clone the repo to a known directory, create a zip of the known directory and hive that off somewhere and you're done... so simple for Hg :).


Thats pretty much it for now for setting up and basics.  If needed I'll be looking at moving from a CVS or SVN repo, but for the moment I'll be playing with my newly minted Hg repo :).