You are on page 1of 9

Private Mercury

Sharing source with Mercurial is not hard. There is quite a good guide at Martin’s Blog and, indeed,
first part of this post will mostly follow his setup.

Sharing sources with password authentication is still not hard but (at least from my perspective) is
not obvious. This post will document my efforts of creating private and password protected
Mercurial storage.

This procedure is tested on Ubuntu 10.04.1 LTS but I would expect it to work on older versions as
well.

First we need to install it’s package.

$ sudo apt-get install mercurial


Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
mercurial-common
Suggested packages:
qct vim emacs kdiff3 tkdiff meld xxdiff python-mysqldb python-pygments
The following NEW packages will be installed:
mercurial mercurial-common
0 upgraded, 2 newly installed, 0 to remove and 63 not upgraded.
Need to get 1,182kB of archives.
After this operation, 4,956kB of additional disk space will be used.
Do you want to continue [Y/n]? Y
Get:1 http://hr.archive.ubuntu.com/ubuntu/ lucid/universe mercurial-common 1.4.3-1
[1,131kB]
Get:2 http://hr.archive.ubuntu.com/ubuntu/ lucid/universe mercurial 1.4.3-1 [50.7kB]
Fetched 1,182kB in 3s (388kB/s)
Selecting previously deselected package mercurial-common.
(Reading database ... 124142 files and directories currently installed.)
Unpacking mercurial-common (from .../mercurial-common_1.4.3-1_all.deb) ...
Selecting previously deselected package mercurial.
Unpacking mercurial (from .../mercurial_1.4.3-1_i386.deb) ...
Processing triggers for man-db ...
Setting up mercurial-common (1.4.3-1) ...
Setting up mercurial (1.4.3-1) ...
Creating config file /etc/mercurial/hgrc.d/hgext.rc with new version
Processing triggers for python-support ...

Create location for Mercurial repositories at /srv/hg with cgi-bin at subdirectory:

$ sudo mkdir -p /srv/hg/cgi-bin


$ sudo cp /usr/share/doc/mercurial-common/examples/hgweb.cgi /srv/hg/cgi-bin/

Additionally we need to create file named “/srv/hg/cgi-bin/hgweb.config” (do not forget to sudo)
with following lines:

[collections]
/srv/hg/ = /srv/hg/
In newer Mercurial installations you also need to edit “/srv/hg/cgi-bin/hgweb.cgi” in order to fix
config parameter. Just change example config line with:

config = "/srv/hg/cgi-bin/hgweb.config"

Next thing to do is installing apache web server:

$ sudo apt-get install apache2


Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1
libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap libssl0.9.8
Suggested packages:
apache2-doc apache2-suexec apache2-suexec-custom
The following NEW packages will be installed:
apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common
libapr1 libaprutil1 libaprutil1-dbd-sqlite3 libaprutil1-ldap
The following packages will be upgraded:
libssl0.9.8
1 upgraded, 9 newly installed, 0 to remove and 62 not upgraded.
Need to get 6,343kB of archives.
After this operation, 10.2MB of additional disk space will be used.
Do you want to continue [Y/n]? Y
Get:1 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main libssl0.9.8 0.9.8k-
7ubuntu8.1 [3,015kB]
Get:2 http://hr.archive.ubuntu.com/ubuntu/ lucid/main libapr1 1.3.8-1build1 [116kB]
Get:3 http://hr.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1 1.3.9+dfsg-3build1
[85.4kB]
Get:4 http://hr.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1-dbd-sqlite3
1.3.9+dfsg-3build1 [27.1kB]
Get:5 http://hr.archive.ubuntu.com/ubuntu/ lucid/main libaprutil1-ldap 1.3.9+dfsg-
3build1 [25.1kB]
Get:6 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main apache2.2-bin 2.2.14-
5ubuntu8.2 [2,622kB]
Get:7 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main apache2-utils 2.2.14-
5ubuntu8.2 [159kB]
Get:8 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main apache2.2-common
2.2.14-5ubuntu8.2 [290kB]
Get:9 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main apache2-mpm-worker
2.2.14-5ubuntu8.2 [2,366B]
Get:10 http://hr.archive.ubuntu.com/ubuntu/ lucid-updates/main apache2 2.2.14-
5ubuntu8.2 [1,484B]
Fetched 6,343kB in 14s (440kB/s)
Preconfiguring packages ...
(Reading database ... 124530 files and directories currently installed.)
Preparing to replace libssl0.9.8 0.9.8k-7ubuntu8 (using .../libssl0.9.8_0.9.8k-
7ubuntu8.1_i386.deb) ...
Unpacking replacement libssl0.9.8 ...
Setting up libssl0.9.8 (0.9.8k-7ubuntu8.1) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place
Selecting previously deselected package libapr1.
(Reading database ... 124530 files and directories currently installed.)
Unpacking libapr1 (from .../libapr1_1.3.8-1build1_i386.deb) ...
Selecting previously deselected package libaprutil1.
Unpacking libaprutil1 (from .../libaprutil1_1.3.9+dfsg-3build1_i386.deb) ...
Selecting previously deselected package libaprutil1-dbd-sqlite3.
Unpacking libaprutil1-dbd-sqlite3 (from .../libaprutil1-dbd-sqlite3_1.3.9+dfsg-
3build1_i386.deb) ...
Selecting previously deselected package libaprutil1-ldap.
Unpacking libaprutil1-ldap (from .../libaprutil1-ldap_1.3.9+dfsg-3build1_i386.deb)
...
Selecting previously deselected package apache2.2-bin.
Unpacking apache2.2-bin (from .../apache2.2-bin_2.2.14-5ubuntu8.2_i386.deb) ...
Selecting previously deselected package apache2-utils.
Unpacking apache2-utils (from .../apache2-utils_2.2.14-5ubuntu8.2_i386.deb) ...
Selecting previously deselected package apache2.2-common.
Unpacking apache2.2-common (from .../apache2.2-common_2.2.14-5ubuntu8.2_i386.deb)
...
Selecting previously deselected package apache2-mpm-worker.
Unpacking apache2-mpm-worker (from .../apache2-mpm-worker_2.2.14-
5ubuntu8.2_i386.deb) ...
Selecting previously deselected package apache2.
Unpacking apache2 (from .../apache2_2.2.14-5ubuntu8.2_i386.deb) ...
Processing triggers for man-db ...
Processing triggers for ufw ...
Processing triggers for ureadahead ...
ureadahead will be reprofiled on next reboot
Setting up libapr1 (1.3.8-1build1) ...
Setting up libaprutil1 (1.3.9+dfsg-3build1) ...
Setting up libaprutil1-dbd-sqlite3 (1.3.9+dfsg-3build1) ...
Setting up libaprutil1-ldap (1.3.9+dfsg-3build1) ...
Setting up apache2.2-bin (2.2.14-5ubuntu8.2) ...
Setting up apache2-utils (2.2.14-5ubuntu8.2) ...
Setting up apache2.2-common (2.2.14-5ubuntu8.2) ...
Enabling site default.
Enabling module alias.
Enabling module autoindex.
Enabling module dir.
Enabling module env.
Enabling module mime.
Enabling module negotiation.
Enabling module setenvif.
Enabling module status.
Enabling module auth_basic.
Enabling module deflate.
Enabling module authz_default.
Enabling module authz_user.
Enabling module authz_groupfile.
Enabling module authn_file.
Enabling module authz_host.
Enabling module reqtimeout.
Setting up apache2-mpm-worker (2.2.14-5ubuntu8.2) ...
* Starting web server apache2
apache2: Could not reliably determine the server's fully qualified domain name,
using 127.0.1.1 for ServerName
Setting up apache2 (2.2.14-5ubuntu8.2) ...
Processing triggers for libc-bin ...
ldconfig deferred processing now taking place

We need new configuration for web interface of our repositories (“/etc/apache2/sites-available/hg”)


with following content:
NameVirtualHost *
<VirtualHost *>
ServerAdmin webmaster@localhost
DocumentRoot /srv/hg/cgi-bin/
<Directory "/srv/hg/cgi-bin/">
SetHandler cgi-script
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/hg.log
<Location />
AuthType Basic
AuthName "Mercurial"
AuthUserFile /srv/hg/.htpasswd
Require valid-user
</Location>
</VirtualHost>

Lines under Location are ones that ensure privacy of our repository.

We can now disable default web site and enable new one (and we can ignore all warnings) together
with changes of ownership and rights:

$ sudo chown -R www-data /srv/hg


$ sudo chmod a+x /srv/hg/cgi-bin/hgweb.cgi
$ sudo a2dissite default
Site default disabled.
Run '/etc/init.d/apache2 reload' to activate new configuration!
$ sudo a2ensite hg
Enabling site hg.
Run '/etc/init.d/apache2 reload' to activate new configuration!
$ sudo /etc/init.d/apache2 reload
* Reloading web server config apache2
apache2: Could not reliably determine the server's fully qualified domain name,
using 127.0.1.1 for ServerName
[warn] NameVirtualHost *:80 has no VirtualHosts

If we try to access “http://localhost” now, we should be greeting with password prompt.

Thing that we are missing is “/srv/hg/.htpasswd” file. We can create all users we need with htpasswd
command:

$ sudo htpasswd -c /srv/hg/.htpasswd testuser


New password:
Re-type new password:
Adding password for user testuser

All further users are then added with slightly modified command (notice that -c is missing):

$ sudo htpasswd /srv/hg/.htpasswd testuser2


New password:
Re-type new password:
Adding password for user testuser2

After creating repository itself


$ sudo hg init /srv/hg/TestRepo

we must also create “/srv/hg/TestRepo/.hg/hgrc” file with following content:

[web]
push_ssl=false
allow_push=testuser

This allows for using http (instead of https) and allows access to our “testuser” (if there are no
restricturons, just put * for user name). Very last step in setup is actually allowing apache to use our
repository for writing. Easiest thing to do here is just transferring ownership to it:

$ sudo chown -R www-data /srv/hg/TestRepo

Finally we can use “http://192.168.0.2/hgweb.cgi/TestRepo/” for pushing and pulling data from any
Mercurial client.

This is print version of post at http://www.jmedved.com/2010/09/private-mercury/.


Mercurial over https
My guide on making Mercurial server left us with http as a protocol of choice. This might be ok in
local network but https would be more comfortable choice. This post starts with already running
Mercurial server on Ubuntu.

Apache does come with https module which has to be enabled:

$ sudo a2enmod ssl


Enabling module ssl.
See /usr/share/doc/apache2.2-common/README.Debian.gz on how to configure SSL and
create self-signed certificates.
Run '/etc/init.d/apache2 restart' to activate new configuration!

Before restarting Apache we need to create few things (key, certificate signing request, certificate)
and easiest way is to create it ourself (write whatever you want for organization details):

$ openssl genrsa -out https.key 1024


Generating RSA private key, 1024 bit long modulus
..........++++++
......++++++
e is 65537 (0x10001)

$ openssl req -new -key https.key -out https.csr


You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, YOUR name) []:
Email Address []:

Please enter the following 'extra' attributes


to be sent with your certificate request
A challenge password []:
An optional company name []:

$ openssl x509 -req -days 36500 -in https.csr -signkey https.key -out https.crt
Signature ok
subject=...
Getting Private key

Once keys are created we must enter following lines in “/etc/apache2/sites-available/hg” (I left other
stuff for clarity):

NameVirtualHost *
<VirtualHost *>
ServerAdmin webmaster@localhost
DocumentRoot /srv/hg/cgi-bin
<Directory "/srv/hg/cgi-bin/">
SetHandler cgi-script
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/hg.log
<Location />
AuthType Basic
AuthName "Mercurial"
AuthUserFile /srv/hg/.htpasswd
Require valid-user
</Location>
RewriteEngine on
RewriteRule (.*) /srv/hg/cgi-bin/hgweb.cgi/$1
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile /srv/hg/https.crt
SSLCertificateKeyFile /srv/hg/https.key
</VirtualHost>

With this we are ready for restart:

$ /etc/init.d/apache2 restart
* Restarting web server apache2
[warn] NameVirtualHost *:80 has no VirtualHosts
... waiting [warn] NameVirtualHost *:80 has no VirtualHosts

After these changes Mercurial is listening ONLY on https. Since we made self-signed certificate,
browser will complain about verification, but that is quite normal.

This is print version of post at http://www.jmedved.com/2011/02/mercurial-over-https/.


Mercurial over both http and https
My last post about Mercurial left us with Mercurial server listening to https-only requests. This is
probably best solution security-wise but there might be valid reasons for having it on http also (e.g.
performance within local network).

Solution lies in editing “/etc/apache2/sites-available/hg” to have two configurations – one for http
and one for https:

NameVirtualHost *:80
NameVirtualHost *:443

<VirtualHost *:80>
ServerAdmin webmaster@localhost
DocumentRoot /srv/hg/cgi-bin
<Directory "/srv/hg/cgi-bin/">
SetHandler cgi-script
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/hg.log
<Location />
AuthType Basic
AuthName "Mercurial"
AuthUserFile /srv/hg/.htpasswd
Require valid-user
</Location>
RewriteEngine on
RewriteRule (.*) /srv/hg/cgi-bin/hgweb.cgi/$1
</VirtualHost>

<VirtualHost *:443>
ServerAdmin webmaster@localhost
DocumentRoot /srv/hg/cgi-bin
<Directory "/srv/hg/cgi-bin/">
SetHandler cgi-script
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/hg.log
<Location />
AuthType Basic
AuthName "Mercurial"
AuthUserFile /srv/hg/.htpasswd
Require valid-user
</Location>
RewriteEngine on
RewriteRule (.*) /srv/hg/cgi-bin/hgweb.cgi/$1
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile /srv/hg/https.crt
SSLCertificateKeyFile /srv/hg/https.key
</VirtualHost>

After quick Apache restart your Mercurial will answer both http and https requests.

This is print version of post at http://www.jmedved.com/2011/02/mercurial-over-both-http-and-


https/.

You might also like