Source: zakaria - Published on 2022-02-15 and updated on 2025-11-20
Note: This guide is severely out of date. The author recommends using ssl-proxy instead of relayd due to changes in the Tailscale protocol regarding web-sockets.
In this post I’ll detail the steps I took to install and configure headscale, an open-source self-hostable implementation of the Tailscale control server, on OpenBSD.
Code blocks prefixed with # imply that the command should be run as a privileged user/root.
Compilation
Since my server is on OpenBSD-stable, headscale is only available via pkg_add on -current, I need to compile the headscale binary by hand and upload it to the server.
$ git clone git@github.com:juanfont/headscale.git
$ cd headscale
$ make generate
$ make build
$ sftp user@server <<EOF
> put ./headscale
> bye
EOF
Then login, get root access, and copy the binary to /usr/local/bin:
$ ssh user@server
$ doas -s
...
# cp ./headscale /usr/local/bin
# chown root:bin /usr/local/bin/headscale
Configuration
Next we need to setup:
- A
_headscaledaemon user that headscale will run as. - Directories for headscale to store its sqlite database, private key, and socket (making sure they have the correct permissions/owner).
- Copy the example config from GitHub, and edit it to our liking.
First we setup some directories:
# mkdir -p /etc/headscale
# touch /etc/headscale/config.yaml
# mkdir -p /var/headscale
Then we add our _headscale daemon user, and chown all the necessary dirs.
# useradd -L daemon -s /sbin/nologin -d /var/headscale _headscale
# chown -R _headscale:_headscale /var/headscale
# doas -u _headscale /bin/ksh
$ touch /var/headscale/db.sqlite
Finally we can edit the headscale config. I highly recommend copying the example config and using that as a starting point.
# vi /etc/headscale/config.yaml
# # copy the example config
# # change domain, IPs, ports
# # change sock location to /var/headscale/headscale.sock
Run headscale serve to see if the config works, and all the directories and permissions are correct:
# doas -u _headscale headscale serve
...
rc.d
I’ve made an init script to making stopping/starting and running at boot a lot easier. Drop this simple script into /etc/rc.d/headscale:
#!/bin/ksh
#
# /etc/rc.d/headscale
daemon_user="_headscale"
daemon="/usr/local/bin/headscale"
daemon_flags="serve"
. /etc/rc.d/rc.subr
rc_cmd $1
chmod, enable and start it as usual:
# chmod +x /etc/rc.d/headscale
# rcctl enable headscale
# rcctl start headscale
headscale(ok)
Clients
OpenBSD client
It’s pretty easy to get the Tailscale client on OpenBSD to use your control server.
# pkg_add tailscale
# rcctl enable tailscaled; rcctl start tailscaled
# tailscale --login-server "https://headscale.example.com:443"
...
Android client
The Android client supports custom Control Server URLs out of the box now. For historical purposes, instructions for patching and building a custom APK can be found here.