Network & Connectivity

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.deb

Base 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.8

Enable and Start

sudo systemctl enable --now headscale
sudo systemctl status headscale

Reverse 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 nginx

User and Authorization Management

Create a User/Namespace

sudo headscale users create myuser

Generate 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 list

Delete a Node

sudo headscale nodes delete -i 1

Expire a Node

sudo headscale nodes expire -i 1

Subnet Routing and Exit Nodes

View Routes

sudo headscale routes list

Enable Subnet Routing

sudo headscale routes enable -i 1 -r 192.168.1.0/24

Configure 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 --version

Troubleshooting

Check Service Logs

sudo journalctl -u headscale -f

Database 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 headscale

gRPC 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.

On this page