Keyboard shortcuts

Press ← or β†’ to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

πŸ” 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