π Headscale Setup Notes
Prerequisites
- Base VPS security setup completed
- NGINX installed and configured
- Domain pointed to VPS IP
- Port 443 available
1. π¦ Installation
Download latest release:
cd /tmp
wget https://github.com/juanfont/headscale/releases/latest/download/headscale_<version>_linux_amd64.deb
Install:
sudo apt install ./headscale_*_linux_amd64.deb
Verify installation:
headscale version
2. βοΈ Configuration
Copy your config to the correct location:
sudo cp headscale.config.yaml /etc/headscale/config.yaml
sudo chown headscale:headscale /etc/headscale/config.yaml
sudo chmod 644 /etc/headscale/config.yaml
Review and edit config as needed:
sudo vim /etc/headscale/config.yaml
Important: Disable built-in ACME (nginx will handle SSL):
acme_email: ""
tls_letsencrypt_hostname: ""
tls_letsencrypt_listen: ""
Create data directory:
sudo mkdir -p /var/lib/headscale
sudo chown headscale:headscale /var/lib/headscale
3. π NGINX Reverse Proxy (HTTP Only - Temporary)
Create nginx config:
sudo vim /etc/nginx/sites-available/<your_domain>
Add basic HTTP configuration:
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
listen [::]:80;
server_name <your_domain>;
location / {
proxy_pass http://localhost:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $server_name;
proxy_buffering off;
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;
}
}
Enable site:
sudo ln -s /etc/nginx/sites-available/<your_domain> /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
4. π SSL Certificate
Get certificate (certbot will auto-configure HTTPS):
sudo certbot --nginx -d <your_domain>
5. π Start Service
Enable and start:
sudo systemctl enable headscale
sudo systemctl start headscale
Check status:
sudo systemctl status headscale
sudo journalctl -u headscale -f
Note: You may see a warning βListening without TLS but ServerURL does not start with http://β - this is expected when using nginx as reverse proxy.
6. π₯ User Management
Create a user:
sudo headscale users create <username>
List users:
sudo headscale users list
7. π± Connect Devices
Generate registration key:
sudo headscale preauthkeys create --user <username> --expiration 1h
On client device:
tailscale up --login-server https://<your_domain> --authkey <key>
List connected nodes:
sudo headscale nodes list
8. π Exit Node Setup (Optional)
Configure the VPS to act as an exit node for routing traffic.
Install Tailscale client on VPS:
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt update
sudo apt install -y tailscale
Enable IP forwarding:
echo 'net.ipv4.ip_forward = 1' | sudo tee -a /etc/sysctl.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Allow forwarding in firewall:
sudo ufw allow in on tailscale0
sudo ufw route allow in on tailscale0
Generate auth key for VPS:
sudo headscale preauthkeys create --user <username> --expiration 1h
Connect VPS to headscale and advertise as exit node:
sudo tailscale up --login-server https://<your_domain> --advertise-exit-node --authkey <key>
9. π οΈ Common Commands
# List all nodes
sudo headscale nodes list
# List users
sudo headscale users list
# Create preauth key
sudo headscale preauthkeys create --user <username>
# Remove node
sudo headscale nodes delete --identifier <node-id>
# Service management
sudo systemctl status headscale
sudo systemctl restart headscale
sudo journalctl -u headscale -n 50
Result β
- Headscale running with SSL
- Ready to accept Tailscale clients
- Self-hosted VPN control server