Headscale
Self-hosted Tailscale coordination server, connect all your devices in a private mesh network without relying on Tailscale's infrastructure
Headscale is an open-source implementation of the Tailscale coordination server. With Headscale, you control your private mesh network. Clients use the official Tailscale app but connect to your server instead of Tailscale's infrastructure.
Requirements
- VPS with public IP address
- Port 443 open (HTTPS)
- Domain name
- Linux x64 system
Installation
Download and Install
# Download latest release
wget https://github.com/juanfont/headscale/releases/download/v0.22.3/headscale_0.22.3_linux_amd64.deb
# Install package
sudo dpkg -i headscale_0.22.3_linux_amd64.debBase Configuration
Edit /etc/headscale/config.yaml:
server_url: https://headscale.yourdomain.com
listen_addr: 127.0.0.1:8080
db_type: sqlite
db_sqlite:
path: /var/lib/headscale/db.sqlite
ip_prefixes:
- fd7a:115c:a1e0::/48
- 100.64.0.0/10
dns_config:
base_domain: yourdomain.com
nameservers:
- 1.1.1.1
- 8.8.8.8Enable and Start
sudo systemctl enable --now headscale
sudo systemctl status headscaleReverse Proxy Setup
Configure Nginx to proxy gRPC and HTTP traffic to Headscale (running on port 8080 localhost):
# /etc/nginx/sites-available/headscale
server {
listen 443 ssl http2;
server_name headscale.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/headscale.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/headscale.yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
server {
listen 80;
server_name headscale.yourdomain.com;
return 301 https://$server_name$request_uri;
}Enable and test:
sudo ln -s /etc/nginx/sites-available/headscale /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginxUser and Authorization Management
Create a User/Namespace
sudo headscale users create myuserGenerate Authentication Key
# Reusable key, expires in 24 hours
sudo headscale preauthkeys create --user myuser --reusable --expiration 24h
# Output: tskey-...Connect Tailscale Clients
Use the official Tailscale app on Windows, macOS, iOS, Android, or Linux:
# Linux example
sudo tailscale up --login-server https://headscale.yourdomain.com --authkey tskey-...All official Tailscale clients (Windows, Mac, iOS, Android, Linux) work seamlessly with Headscale. Use the same app, just point it to your server.
Managing Nodes
List Connected Nodes
sudo headscale nodes listDelete a Node
sudo headscale nodes delete -i 1Expire a Node
sudo headscale nodes expire -i 1Subnet Routing and Exit Nodes
View Routes
sudo headscale routes listEnable Subnet Routing
sudo headscale routes enable -i 1 -r 192.168.1.0/24Configure Exit Node
After a node is connected and has subnet routing enabled, clients can use it as an exit node through the Tailscale app UI or CLI.
Updates
# Download new release
wget https://github.com/juanfont/headscale/releases/download/v0.23.0/headscale_0.23.0_linux_amd64.deb
# Install (service restarts automatically)
sudo dpkg -i headscale_0.23.0_linux_amd64.deb
# Verify
sudo headscale --versionTroubleshooting
Check Service Logs
sudo journalctl -u headscale -fDatabase Issues
# Backup database
sudo cp /var/lib/headscale/db.sqlite /var/lib/headscale/db.sqlite.bak
# Reset database (CAUTION: removes all data)
sudo rm /var/lib/headscale/db.sqlite
sudo systemctl restart headscalegRPC Connection Issues
Verify Nginx is passing gRPC correctly with curl:
curl -i --http2 https://headscale.yourdomain.com/Should return HTTP/2 response.
Do not expose Headscale directly to the internet without TLS. Always use a reverse proxy with valid SSL certificates.