HGKeeper is an server for mercurial repositories. It provides access control for SSH access and public HTTP access via hgweb.

It was originally designed to be run in a container but recently support has been added to run it from an existing openssh-server.


HGKeeper is licensed under the GNU AFFERO GENERAL PUBLIC LICENSE version 3.


This project is brand new and only lightly tested. If you find issues, or are looking for ways to help, please check out our issue tracker.


This project needs to generate some source files, so you'll need to first install the embedding tool esc.

$ go get -u

Once esc is installed, make sure it's available on your path.

Then you can build hgkeeper with the following commands:

$ go generate ./...
$ go build

Getting Started

The initial setup of HGKeeper has a few steps.

SSH Host Keys

Since HGKeeper provides an SSH server you will need to generate host keys for it if you are going to use it. You can skip the SSH server by passing --disable-ssh or setting the HGK_DISABLE_SSH environment variable to true. This is useful if you just want to provide a read only repositories.

You can generate SSH host keys for whatever type you like, but rsa will cover just about everyone. That said, a lot of people prefer to use ed25519 as well.

By default the SSH host keys will be looked for in the directory host-keys in the current working directory. This can be changed with the --ssh-host-keys-path or -H command line arguments to hgkeeper.

This directory will be read and files in it will attempt to be loaded into the server.

To generate a host key you can use the following command, note that you can create other types via the -t option, but you should read the ssh-keygen documentation as other options are avaiable for each type.

$ ssh-keygen -t rsa -b 4096 -o host-keys/ssh_host_rsa_key

Create the hgkeeper repo

Before you can run the server we need to create the hgkeeper admin repository. This can be done via hgkeeper setup. You will need to pass the arguments --admin-username which is the name of the admin user, as well as --admin-pubkey which is the path to the SSH public key for the new admin user. By default this will create a new repository under repos/hgkeeper. There are some additional options which you can discover via hgkeeper setup --help.


hgkeeper has a couple of modes of operation but serve is the main mode.


The setup command is used to bootstrap HGKeeper. It will create the directory for the repositories as well as the hgkeeper repository.

After initial setup, please make sure to read the in the hgkeeper admin repository that was created, as it details how access control works.


The serve command is the main mode of operation which is to provide access to the repositories.

You can optionally disable either one of the HTTP or SSH servers to limit resources or just disable the portions you don't need.

For example, say you don't need public access or the web interface at all, you can disable it by passing --disable-http to the serve command or by setting the HGK_DISABLE_HTTP environment variable to true.

Likewise, if you just want to serve up a read only repositories over http you can disable the SSH server by passing --disable-ssh to the server command or by setting the HGK_DISABLE_SSH environment variable to true.

These two options are mutually exclusive and passing both will stop HGKeeper from starting.

Access Control

Access control is defined in the hgkeeper admin repository that is created via the hgkeeper setup command. It is implemented via casbin using the RBAC with deny-override model as a base. More information can be found in the files that are placed in the hgkeeper admin repository.

Running in a Container

HGKeeper is available on docker hub under rwgrim/hgkeeper and is updated via CI.

Just like running locally, running in the container is going to require at least one ssh host key and an hgkeeper admin repository.

For the rest of these instructions we are going to assume that you have your ssh host keys in a directory named host-keys in the current working directory.

Once you have your ssh host keys generated you can create the hgkeeper admin repository by running the container with an overridden command.

An extra step to this is that you'll need to volume mount in a file containing the public key of the initial administrator of this instance. In the following example we assume that that key is in ~/.ssh/

Also, since this container is just used for initialization of files on the host, we're passing the --rm flag to make sure it's deleted when done.

We can now run the initialization setup that follows.

docker run --rm \
    -v $(pwd)/repos:/repos \
    -v ~/.ssh/ \
    -e HGK_ADMIN_USERNAME=my_username \
    -e HGK_ADMIN_PUBKEY=/admin-pubkey \
    -e HGK_REPOS_PATH=/repos \ \
    hgkeeper setup

Once this step is done you should now have a repos directory in your current working directory and it should have a brand new hgkeeper admin repository in it.

Now that your hgkeeper admin repository is all ready to go you can run HGKeeper in its normal serve mode.

The following example uses the same assumptions as the setup container above, but it is also going to expose the container on the host's network interface. The following example runs the container in the background, gives it a name of hgkeeper, and sets it to always restart. If you're just doing testing, you will probably want to remove the -d (background), --name hgkeeper (name), and --restart=always options.

docker run -d --name hgkeeper \
    --restart=always \
    -v $(pwd)/host-keys:/host-keys:ro \
    -v $(pwd)/repos:/repos \
    -e HGK_SSH_HOST_KEYS=/host-keys \
    -e HGK_REPOS_PATH=/repos \
    -p 8080:8080 \
    -p 22222:22222 \ \
    hgkeeper serve

And that's it! You can now access your instance via the hosts IP address or DNS and you're good to go!

Of course, you'll probably want to add some more users. To find out how to do that, be sure to read the in the hgkeeper admin repository.

Running Locally

Once the SSH host keys and the hgkeeper admin repository are created, you can run HGKeeper with hgkeeper serve. There are some other options that are available so be sure to check out hgkeeper serve --help.

Running locally with an OpenSSH Server

There are a number of steps to integrate HGKeeper with OpenSSH Server and some of them vary across operating systems. If you run into a case where these instructions do not work for you, please reach out via the issue tracker so we can help you and fix the documentation.

Creating the hg user

When it comes to integrating with OpenSSH server you need to create a user that will run HGKeeper during SSH connections and own the repositories on disk. This user can be named whatever you like, but for the purposes of this documentation we will be naming the user hg.

For most Linux distributions, you can create the hg user with the following command:

useradd --home-dir /var/lib/hg --create-home --system --shell /usr/sbin/nologin

Setup HGKeeper

To get HGKeeper fully running, you will need to run hgkeeper setup to create the hgkeeper admin repository as well as the initial admin user. Once this repository is created, make sure it and it's parent directory is owned by the hg user and that the hg user has write permission.

Installing HGKeeper

OpenSSH server has some very specific requirements for calling applications directly. These requirements are that the executable as well as all of the directories leading up to the executable must be owned by root and not writeable by the group or other users. To deal with this, we will be installing HGKeeper into /usr/local/bin. This directory should fulfill all of the those requirements. So just sudo cp hgkeeper /usr/local/bin/ and make sure that it is owned by root with a file mode of 755.

Configuring OpenSSH Server

The OpenSSH configuration is actually quite easy, you just need to drop the following snippet into /etc/ssh/sshd_config. Of course, if you customized the install location or user name you'll have to adjust that in the snippet below. Note that the value for --repos-path needs to be the absolute path to your repositories.

You may be able to use /etc/ssh/sshd_config.d/hgkeeper.conf but in our testing on Debian unstable we were unable to get it working.

Match User hg
    AuthorizedKeysCommand /usr/local/bin/hgkeeper --repos-path=<path to your repositories> authorized-keys %f
    AuthorizedKeysCommandUser hg

Once you've created the file, you'll need to reload OpenSSH Server. This is usually done via service ssh reload but may vary based on your operating system.

Once you've reloaded OpenSSH Server you should be able to clone the hgkeeper admin repository with hg clone ssh://hg@yourhostname/hgkeeper as long as the machine you're cloning from has the private key that you added as your initial admin user.

Creating Respositories

Creating a new repository in HGKeeper is just the same as using mercurial over SSH. That is, you can use the hg init command with a path to HGKeeper. As long as you have init permission for the path HGKeeper will create an empty repository for you.

For example, if you wanted to create a new repository named myteam/new-project-1, you would do so with hg init ssh://hg@my-hgkeeper-domain/myteam/new-project-1. If there were no issues, the command will exit without error and you are now free to clone it with hg clone ssh://hg@my-hgkeeper-domain/myteam/new-project-1.

Known Errata

no mutual signature algorithm

Fedora 33 disabled ssh-rsa by default in openssh-client. This breaks the golang x/crypto/ssh library. See this bug for more details.

The current work around for this is to add a host block in your ssh client configuration to re-enable ssh-rsa. See the following example:

Host <hgkeeper hostname>
    PubkeyAcceptedKeyTypes ssh-rsa
Recent Changes