GoatCounter self-hosted setup on a VPS


Goatcounter is a lightweight, privacy-friendly, open-source analytics server. I wanted to self-host it, couldn’t find a good guide on how to do it from scratch on a fresh VPS, and decided to write this up after some trial and error.

Other guides which may be useful if something here doesn’t work:

VPS setup

Create a new VPS…

…or use an existing one, goatcounter just needs free ports 80 and 443 (if you want to run it behind a reverse proxy on another port, you can, but you’ll have to adjust the setup script a bit). For this guide, I’m using Arch Linux on Linode, as it’s a rolling release (nice if you don’t wanna take care of the VPS too much) with reasonably small userspace. Most other distros are needlessly large out-of-the-box. On the other side, Alpine doesn’t have systemd and other niceties, so I wouldn’t recommend that either.

Basic distro setup

Add your SSH key (on Linode, you can do this even before creating the VPS) and disable password authentication. If you want to deal with a firewall, this would be a good time to also set it up.

The setup script below will create a goatcounter user automatically and run goatcounter under it. It could be hardened a bit further with chroot (RootDirectory=... option in systemd) and path whitelisting, but there are some issues with it and this is “secure enough” for most uses (just make sure you don’t give read access for all users to anything interesting on the VPS).

Domain setup

Goatcounter seems to expect that you have a domain you can use for it. I didn’t try using the VPS IP directly, nor would I recommend it. So, setup a DNS entry for your VPS, and enter the domain in the next step.

GoatCounter installation & setup

I wrote an automated script that should set everything up. Goatcounter v1.4.2 is hardcoded, but feel free to change it, I was just too lazy to automate download of the latest version from GitHub. You may also change $install_dir if you want to. Upload it to the VPS, chmod +x and run. In case something fails, it should be safe to rerun the script again.


After the script finishes (it will prompt you for domain, e-mail and password), goatcounter should be up and running. If all goes well, it will retrieve a Let’s Encrypt TLS certificate on its own, otherwise it will hopefully print an error and tell you what to fix.

Try to connect to it over HTTPS (use the domain you entered earlier) and log in using the entered credentials (e-mail and password). If you are able to successfully authenticate, add the client JS script tag to your website, test that it correctly records the visit and you should be done.

If something in the script doesn’t work for you, send me an e-mail at nulya@actually.fyi, hopefully I’ll find some time to figure it out.