
Tailscale is an open-source VPN. It works very well. However, its control server is still on their systems. Headscale is an open-source, self-hosted implementation of the Tailscale control server.
Here, I’ll list down the steps required to install Headscale on Ubuntu.
Download the correct Headscale version
- get the latest release number from Github Releases Page
- get system architecture (for Linux,
amd64)
Use the following command to get the correct version. Substitute the version number from 1 above and the system architecture from 2.
HEADSCALE_VERSION="0.27.1"
HEADSCALE_ARCH="amd64"
wget --output-document=headscale.deb \
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
Install the Headscale server
sudo apt install ./headscale.deb
Modify config.yaml
The Headscale config.yaml is available in /etc/headscale/config.yaml
The following variables need to be set there:
server_url, listen_addr, metrics_listen_addr
Since, the headscale server will be running behind a proxy, these variables will point to 127.0.01
server_url: http://127.0.0.1:8081
listen_addr: 127.0.0.1:8081
metrics_listen_addr: 127.0.0.1:9091
Start the Headscale server
sudo systemctl start headscale
Install and run Headscale UI
Now, that Headscale has been set up, a UI is needed to be able to add the clients. For this, I used Headscale UI, and open-source front-end for the the Headscale control server.
Headscale UI docker-compose.yml file
services: headscale-ui: container_name: headscale-ui image: ghcr.io/gurucomputing/headscale-ui:latest restart: unless-stopped ports: - "127.0.0.1:9080:8443"
Nginx Proxy
Nginx sits in front of both Headscale and Headscale UI. It handles the SSL certs from LetsEncrypt.
map $http_upgrade $connection_upgrade {
default keep-alive;
'websocket' upgrade;
'' close;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
ssl_certificate /path/to/cert;
ssl_certificate_key /path/to/key;
server_name headscale.your-domain.com;
server_tokens off;
access_log /var/log/nginx/headscale_access.log;
error_log /var/log/nginx/headscale_error.log;
# Headscale UI (gurucomputing) – e.g. https://headscale.your-domain.com/web
# DON'T USE /admin as that is expected by the headscale app and will not work
location /web {
proxy_pass https://127.0.0.1:9080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Headscale API and control – everything else
location / {
proxy_pass http://127.0.0.1:8081/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_read_timeout 86400;
}
}
server {
listen 80;
listen [::]:80;
server_name headscale.your-domain.com;
server_tokens off;
return 301 https://$host$request_uri;
}
Test and reload Nginx
nginx -t
nginx -s reload
This sets up both Headscale and Headscale UI
Leave a Reply