🍄Setup Fossil On Openbsd

I have most of my repositories hosted on GitHub and Sourcehut using Git. I also tried Mercurial on Sourcehut. My general impressions are:

  • Git is the most popular option and the de-facto standard if you want any collaboration happening. At the same time this is the least user-friendly option for the workflow I have. Currently I'm trying legit that offers a better UI.

  • Mercurial is very similar to Git, the most advantageous feature to me is the ability to have multiple "detached heads" ("bookmarks" in Mercurial). Mercurial is a literal DAG where you can visit different leafs ("heads") without any problems. It also has a somewhat nicer user interface. But it is too similar to Git and doesn't have enough benefits to switch.

I usually have these cases for VCS:

  1. Personal repositories where I'm the only committer.

  2. Repositories with rare contributions where the code is a library that can be useful to others.

  3. Work.

I think that for cases (2) and (3) I will still have to use Git because of GitHub (or whatever the Git forge with "pull request workflow" is the most popular right now). But for personal things it makes sense to use something I host on my own server.

Both Git and Mercurial are somewhat expensive in terms of hosting because Git is a relatively large program with many files and ad-hoc binaries, and Mercurial is a Python application. I think that Fossil is a viable alternative. It is a somewhat unconventional VCS, but it is a very powerful package with version control, wiki, tickets and a powerful history view all in a single binary with a single SQLite database as a storage.

Local Fossil setup

First setup a local repository with fossil init and follow any advice on setting up a server you find useful. I have made the repository completely private, changed the password for the default user and set up a project name and such things.

Later this local repository will be copied to the server.

Remote Fossil setup

It's time to set up the infrastructure on the server, run all commands as root.

Install Fossil:

pkg_add fossil
# choose plain, non-static option

Create a user, set up a directory with repositories:

mkdir /var/fossil
useradd -c "Fossil User" -d /var/fossil -s /sbin/nologin -L daemon _fossil
chown _fossil:_fossil /var/fossil/

From the client, copy the initialized database to the server:

scp scripts.fossil alice@greenfork.me:~

On the server, copy and change permissions for the database:

mv /home/alice/scripts.fossil /var/fossil
chown _fossil:_fossil scripts.fossil

Add /etc/rc.d/fossil service:

#!/bin/ksh

daemon="/usr/local/bin/fossil"
daemon_user="_fossil"
daemon_flags="server /var/fossil --errorlog /var/fossil/errorlog \
        --localhost --repolist --port 1736 --https"
daemon_logger="daemon.info"

. /etc/rc.d/rc.subr

# This service may have erroneous process name, as in ps(1), it must
# be the same as "$daemon $daemon_flags", otherwise rc will fail to
# start it. If this is a problem, the option below may help.
pexp="$daemon server /var/fossil .*"

rc_reload=NO
rc_bg=YES

rc_cmd $1
  • Since we are running through a proxy, options --localhost and --https must be specified.

  • The command in ps(1) is mangled and is not exactly like the one specified in daemon_flags, so we use the pexp hack to not confuse rc(8).

Start it and enable:

rcctl start fossil
rcctl enable fossil

Expose to the internet

Use the Setup Mycorrhiza on OpenBSD article in order to expose this service to the internet, right now it only runs locally.

Make sure to ignore any overriding of Content-Security-Policy in relayd.conf(5), let Fossil serve its own header. If you have Referrer-Policy set to no-referrer, submitting forms will not work, the value should be changed to same-origin as the next most secure header.

Security audit

Follow to Admin -> Security-Audit and go through any recommendations present there. If there are any problems, be sure to also check /test_env for any suspicious values.

Connect local and remote

We can now add the default remote to our local repository and synchronize them:

fossil remote https://grfork@fossil.greenfork.me/scripts
fossil sync

Make sure to set grfork@ to your username.

And that's it! You should have a working Fossil server.

Bonus: create another repository

Now, when we have a working repository, we can use it to create another one. The already created repository will serve as a template for a new one. The only thing left to do is to set a password for the admin user since it is not transferred from a template. And to set proper Unix permissions.

fossil init --template /var/fossil/scripts.fossil --admin-user grfork \
    --project-name "dotfiles" --project-desc "Personal dot files" \
    /var/fossil/dotfiles.fossil
fossil user password grfork ******** --repository /var/fossil/dotfiles.fossil
chown _fossil:_fossil /var/fossil/dotfiles.fossil

Now you can access it in the list of all repositories and you are ready to clone it:

fossil clone https://grfork@fossil.greenfork.me/dotfiles