Setup Mercurial and HgWeb on OpenBSD
Recently I moved my personal repositories from Git to Mercurial, mostly out of curiosity to try something new. It went well, and I thought that it would be nice to have these repos synced remotely and also exposed on the web in read-only mode. I had one OpenBSD server already, the one that powers this blog, so it made sense to me to set up Mercurial server and HgWeb there as well. What seemed like a straightforward task turned out to be a bit more complicated; in order to not forget all the useful information I learned while solving it, this article appeared.
I use OpenBSD 6.3 in the article; for other versions things might be slightly different.
Preparation
I assume that you've already set up DNS for the server. Here and further I'm
going to use hg.nkly.me
as a server name.
Don't forget to update your OpenBSD installation with the newest patches before proceeding:
# syspatch
Setting up Mercurial server
Install Mercurial:
# pkg_add mercurial
Create separate user that will interact with repos:
# useradd -v -m hg
# passwd hg
That's it. After adding SSH keys to hg
user you can create, pull and push
repositories from the server:
$ ssh hg@hg.nkly.me 'hg init test-repo'
$ hg clone ssh://hg@hg.nkly.me/test-repo
... make and commit changes ..
$ hg push ssh://hg@hg.nkly.me/test-repo
Setting up HgWeb
HgWeb is a CGI-application, so we need an external HTTP server in order to run
it on the web. Luckily OpenBSD contains simple yet powerful HTTP daemon httpd
by default, but it supports only FastCGI apps. There is another daemon,
slowcgi
, that is an adapter for CGI apps; it's tricky, however, to use it for
apps in Python or other interpreted languages because it chroots the app to
/var/www
, so in order for it to run the app you need to copy each and every
library and executable that it depends on, as well as to remount /var
as
wxallowed
.
There is another solution though: we can use flup
Python package to convert
HgWeb app between CGI and FastCGI. Let's install it:
# pkg_add py-flup
Then copy HgWeb script and edit it:
$ cp /usr/local/share/mercurial/hgweb.cgi /home/hg/hgweb.py
Here is how my HgWeb script looks like:
#!/usr/local/bin/python2.7
# Path to repo or hgweb config to serve (see 'hg help hgweb')
config = "/home/hg/hgweb.conf"
from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb import hgweb
from flup.server.fcgi import WSGIServer
application = hgweb(config)
WSGIServer(application, bindAddress=("127.0.0.1", 9001)).run()
The script will spawn FastCGI server on 127.0.0.1:9001. Now let's configure
httpd
to send all requests to the FastCGI app. Open /etc/httpd.conf
in your
favorite editor and add the following lines:
server "hg.nkly.me" {
listen on * port 80
fastcgi socket ":9091"
}
Finally let's configure HgWeb itself by creating config file
/home/hg/hgweb.conf
and editing it:1
[ui]
username = Nikolai Obedin <dev@nkly.me>
[paths]
/ = /home/hg/repos/*
[extensions]
highlight =
[web]
highlightfiles = size('<1M')
allow_archive = gz, zip
logourl = https://hg.nkly.me
In order for the highlighter to work, you need to have Pygments installed:
# pkg_add py-pygments
Now it all works well, but it would be even better if we could start, stop and
query status of HgWeb without wrapping it in screen
or something similar, so
let's write a daemon for it. OpenBSD daemons are just shell scripts having
specific structure 2 They reside in /etc/rc.d/
directory. Let's create a new file there, hgwebd
, and edit it:
#!/bin/ksh
daemon="/home/hg/hgweb.py"
daemon_user="hg"
. /etc/rc.d/rc.subr
# Regexp used in pgrep/pkill to ry status/stop the daemon
pexp="/usr/local/bin/python.*${daemon}"
# Disable `rcctl reload` command
rc_reload=NO
# Daemonize the process because hgweb.py doesn't do it by itself
rc_bg=YES
rc_cmd $1
After makinig it executable you can start, stop or check HgWeb status simply by
running rcctl
commands.
Conclusion
Though setting up HgWeb was more involving than e.g. CGit, it didn't take a lot of time, thanks to the clear and extremely helpful documentation of OpenBSD. I really like the approach of lesser features and simpler configurations that OpenBSD team employs; it makes system administration easier and safer overall.
-
Unfortunately there is no single source of documentation for HgWeb configuration. The best resource that I found is https://www.mercurial-scm.org/wiki/PublishingRepositories#hgweb