My Current Single-User Fossil Server Setup


Git was the first proper version control software I've used, and I've only used Git till now; I believe that one should learn as many ways of solving the same problem as possible so that he would not be biased and have a better imagination and intuition at solving similar problems; and "only know about Git" does not align with that idea very well, so I decided to try out other solutions.

The one I've decided that I would use, at least for now, is Fossil. It is made by the team who made SQLite, it is the VCS used by SQLite, and it comes with a lot of very handy things; all the Git setups I've used (GitLab; Gitea; cgit + gitolite) did not come as efficient as Fossil for my use case of "one single dev hosting his own stuff" in terms of resource usage and functionalities.

I've recently switched to a new server running Debian (the previous one runs Arch and it somehow broke when I was doing pacman -Syu); it is quite easy to setup, and I shall record how I did that there.

First install NGINX:

apt-get install nginx
systemctl enable nginx
systemctl start nginx

And Fossil:

apt-get install fossil

And create a user specially for hosting Fossil repositories. Things like Gitea and GitLab also do the same thing; if you have ever cloned with SSH you should have noticed that the remote URL is like git@git.[domain]; the git part before the at sign is the user name for the user that deals with all hosted Git repositories.

useradd -m fossil
# we will put the things in /home/fossil/museum.
# "museum" is a Fossil convention; you can put it anywhere else.
mkdir ~/museum

We need to setup Fossil as a daemon. Put this in /etc/systemd/system/fossil.service:

[Unit]
Description=Fossil server
After=network-online.target

[Service]
User=fossil
Group=fossil
WorkingDirectory=/home/fossil/museum
ExecStart=/usr/bin/fossil server --port 19001 . --files '*.txt,*.html,*.css,*.svg,*.png'
Restart=always
RestartSec=3

[Install]
WantedBy=multi-user.target

Basically what we are doing here is to start Fossil's built-in web server and bind it to port 19001. We select the current working directory, so that all Fossil repositories (they are in the form of SQLite databases) whose file name ends with .fossil would have a web interface. The *.txt,*.html,*.css,*.svg,*.png part is to config the extension names of the files that would be served by the Fossil server as static files. The reason you might want to do this is that when selecting a directory for the Fossil web server the root route (i.e. /) does not work (it would return 404, because there isn't a repository that matches the root route) until you add the --repolist argument, but it really only gives a list of repository it has found and it seems like there's no way to customize that (or maybe I just didn't read enough documentation). Anyway, in my setup I redirected / to /index.html and configured Fossil to serve /index.html as a static file (this will be mentioned later).

And then start Fossil:

systemd daemon-reload
systemd enable fossil
systemd start fossil

And then we can put fossil repo in /home/fossil/museum; they should be available at [ip]:19001/[Name]. The setup of domain name comes later.

Now, setup nginx reverse proxy like this:

location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://127.0.0.1:19001;
}

Setup your domain, wait for the DNS record to propagate, and then run certbot (for https). After that, edit the fossil service file and reload. First change the service file:

ExecStart=/usr/bin/fossil server --port 19001 . --files '*.txt,*.html' --https

And then reload:

systemd daemon-reload
systemd restart fossil.service

Now it's a good time to configure the repository to have the correct base URL.

Setup index redirect at NGINX config like I've mentioned above:

location = / {
        absolute_redirect off;
        return 301 /index.html;
}
location = /index.html {
        try_files $uri =404;
}

Restart NGINX service. After nginx restart, these things should happen:

Now, the simplest method of managing repos (i.e. uploading & deleting) is to do it via sftp; this requires your ssh keys to be authorized for the fossil user. Put your public key in /home/fossil/.ssh/authorized_keys.

After the last step, everything should be done. To push & pull via ssh, you need to use the full url:

fossil update ssh://[username]@[domain]/[path-to-your-fossil-repo-file]

in my setup the username is fossil and the files are at /home/fossil/museum, so for repo fossiltest.fossil the command is:

fossil update ssh://fossil@[domain]//home/fossil/museum/fossiltest.fossil

Good thing in most of the time I only need to do this once since Fossil remembers the last URL you synced with.


Back

Last update: 2024.7.12