Setting up private SSH-based Mercurial repo hosting on Centos
In this tutorial, I walk through the steps to setup Mercurial repo hosting using Mercurial-server on Centos, and setting up Putty+Mercurial on Windows to enable access. There are a lot of small things that seemed to be missing from the existing guides, so I try to cover those to help you save time in getting this set up.
1. Install mercurial-server
As stated on http://mercurial.selenic.com/wiki/SharedSSH, Mercurial-server is not a server but rather a management interface which uses a single shared SSH login for access and some additional logic to allow user rights to be limited. Installing mercurial-server (version 1.0.1) on Centos requires that you tweak the makefile a bit, because it was originally designed for Debian-based systems and there are a few problems. Unfortunately, I haven't found a repo that would have mercurial-server, so there are a couple of manual steps involved. First, install the prerequisites:bash
yum install python python-setuptool* mercurial make
Then, download the source from http://www.lshift.net/mercurial-server.html and untar it on the server.
Open "Makefile" in the source directory, and make the following changes:
- For the line "installfiles: installetc installdoc pythoninstall", remove "installdoc". Result should be "installfiles: installetc pythoninstall". The reason why this is necessary is documented here.
- For the line saying "useradd --system --shell /bin/sh ", change to "useradd -r --shell /bin/sh ". At least for me, the useradd command did not recognize the --system switch, so I had to use -r instead. I guess you could also remove it.
bash
make setup-useradd
(need root privileges) . I remember getting some minor warning, but it didn't seem to be a problem.
2. Copy your public key which you want to use to login onto the server
As stated in the Mercurial-server docs, you need to add the public key you want to use into /etc/mercurial-server/keys/root/put-your-username-here/put-an-easy-to-remember-name-for-your-keyfile-here . If you are using Putty, make sure you have allowed agent forwarding under Connection -> SSH -> Auth -> Authentication parameters -> Allow agent forwarding so that ssh-add will work properly. This way you don't have to mess around with Puttygen (well, the alternative is just to open the file, then paste the OpenSSH format public key to a file and then uploading it). Then run refresh-auth. It is actually under /usr/local/share/mercurial-server/refresh-auth instead of /usr/share (as it is in the documentation). Here are the steps on the remote server after logging in (from mercurial-server documentation):bash
$ ssh-add -L > my-key
$ sudo mkdir -p /etc/mercurial-server/keys/root/your-username
$ sudo cp my-key /etc/mercurial-server/keys/root/your-username/an-easy-to-remember-name-for-keyfile
$ sudo -u hg /usr/share/mercurial-server/refresh-auth<span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: x-large;"><span style="line-height: 19px; white-space: normal;"><strong>
</strong></span></span>
3. Ensure that you can login using hg@yourserver
You first need to be able to login as hg before you can use the system. So test this out by connecting to the server using Putty (obviously, this has to be public key auth, not password auth - Google for a better tutorial on that if necessary). Most likely, you will need to first unlock the hg account. This is because under Red Hat-based distros, users are created in a locked state (= unable to login, see also: documentation). This will show up under /var/log/secure as "sshd[15245]: User hg not allowed because account is locked". To unlock the hg user, setup the account password using:bash
passwd hg
This should result in the account becoming unlocked.
If you are still unable to login, check the sshd_config file under /etc/ssh/sshd_config.
There are a couple of settings that have to be in place, most obviously:
bash
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
AllowUsers hg and-all-the-other-allowed-users
and have a look for AllowGroups/DenyGroups/DenyUsers. Remember that AllowUsers is a whitelist, you have to specify all the accounts that are allowed to log in using ssh (separated by spaces). Not having it set should be equivalent to "AllowUsers *".
Remember to restart sshd if you do change the settings.
4a. Setup Mercurial on Windows to use the correct key
If you are using Putty on Windows for your client repo access, you need these settings. In C:UsersaccountnameMercurial.ini, add the following under the [ui] section:bash
ssh="C:Program Files (x86)PuTTYplink.exe" -ssh -2 -batch -C -i "D:some-pathkey-file.ppk"
To test the connection, run:
bash
"C:Program Files (x86)PuTTYplink.exe" -ssh -2 -batch -C -v -i "D:some-pathkey-file.ppk" hg@servername ls
You should be able to login.
If you keep getting another IP address, make sure your Putty default settings IP is empty. And if you get a "Disconnected: User aborted at host key verification", log in once using Putty and accept the server's host key.
4b. Setup Mercurial on Fedora/Centos/Redhat to use the correct key
If you are using ssh+hg on Linux for your client repo access, you need these settings. You will need to add your key to the /var/lib/mercurial-server/.ssh/authorized_keys file, either manually or by using the steps in stage 2. To set up the private key, edit or create ~/.ssh/config: Host servername-or-ip User hg IdentityFile ~/path-to-keyfile To test the connection, run: ssh servername-or-ip To set up the default pull and push locations for hg push and hg pull, change .hg/hgrc: [paths] default = ssh://hg@servername/reponame default-push = ssh//:hg@servername/reponame Further, much more detailed documentation on the hgrc file is available from Selenic.5. That's it, clone your repo to the server
hg clone --debug -v . ssh://hg@servername/name-of-the-repo
The additional switches will help in showing what is being done.
BTW, remember to specify the source for what you are cloning (e.g. ".").
Comments
Roshan: Shameless Plug: If you care, there is also hg-gateway for scenarios where you don't have root access on the machine, such as the case with shared hosting accounts.
Nick Doyle: Thanks for the writeup. Heads-up: mercurial-server apparently written for python 2.5+ while default CentOS 5.5 yum repositories currently are at 2.4.3 Resulting issue comes when hg push:
remote: error: changegroup.aaaaa_servelog hook raised an exception: 'module' object has no attribute 'SEEK_END'
According to python doco os.SEEK_END is new in python 2.5, with a value of 2 http://docs.python.org/library/os.html
Need to either install python 2.5+ or like my quick hack, edit 2 files and replace "os.SEEK_END" with the number 2 Files needed to edit are: build/lib/mercurialserver/servelog.py src/mercurialserver/servelog.py
dEadY: My first hg push gave me the following error, after I added a public key in the hgadmin repository:
remote: added 1 changesets with 1 changes to 1 files remote: error: changegroup.aaaaa_servelog hook raised an exception: No module named simplejson
Since that error I'm not able to access the server:
remote: mercurial-server: access denied abort: no suitable response from remote hg!
I've installed the python-simplejson package on the server, but of course that doesn't change the fact that I can't login anymore. I've checked mercurial's key directories (nothing changed there) and again executed sudo -u hg /usr/local/share/mercurial-server/refresh-auth but no luck so far. Any idea how to fix that again?
John Airey: I've hit on this problem twice the solution is this in ~hg/.bashrc
export PYTHONPATH='/usr/local/share/mercurial-server'