← All articles
a close up of a computer motherboard with wires

Headscale: Run Your Own Tailscale Control Server (Free and Open Source)

Networking 2026-02-28 · 4 min read headscale tailscale wireguard vpn mesh-networking self-hosted
By Selfhosted Guides Editorial TeamSelf-hosting practitioners covering open source software, home lab infrastructure, and data sovereignty.

Tailscale is one of the best networking tools ever made — it turns your devices into a secure mesh network with zero configuration, automatic NAT traversal, and a dead-simple client. The technology is outstanding.

Photo by Axel Richter on Unsplash

The catch: it's a paid service. Free plan has a 3-device limit. Beyond that, it's $5–$6/user/month.

Headscale solves this. It's an open-source, self-hosted implementation of the Tailscale control server — the brain that coordinates which devices can talk to each other. You keep using the official Tailscale client on all your devices, but your headscale server replaces Tailscale's hosted infrastructure.

Headscale architecture showing self-hosted control server coordinating device connections across the network

How Tailscale Actually Works (And Where Headscale Fits)

Tailscale has two components:

  1. Client (installed on each device): Manages the WireGuard tunnel between devices
  2. Control server (Tailscale's infrastructure): Coordinates the network — authenticates users, distributes IP addresses, manages ACLs, enables device discovery

The client software is open source. The control server is Tailscale's proprietary hosted service (what you pay for).

Headscale reimplements the control server API. You configure the Tailscale client to connect to your headscale server instead of login.tailscale.com. The WireGuard tunneling between devices still works identically — headscale just handles the coordination.

What Headscale Gives You

What You Give Up

Like what you're reading? Subscribe to Self-Hosted Weekly — free weekly guides in your inbox.

Prerequisites

Headscale itself uses minimal resources — a $4/month VPS handles hundreds of devices easily.

Installation

Docker Compose (Recommended)

Create a directory and config file:

mkdir -p /opt/headscale/config

Create /opt/headscale/config/config.yaml:

server_url: https://headscale.yourdomain.com
listen_addr: 0.0.0.0:8080
metrics_listen_addr: 0.0.0.0:9090

private_key_path: /var/lib/headscale/private.key
noise:
  private_key_path: /var/lib/headscale/noise_private.key

ip_prefixes:
  - fd7a:115c:a1e0::/48
  - 100.64.0.0/10

derp:
  server:
    enabled: false
  urls:
    - https://controlplane.tailscale.com/derpmap/default

database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite

log:
  level: info

dns_config:
  magic_dns: true
  base_domain: yourdomain.internal
  nameservers:
    - 1.1.1.1

acls_policy_path: /etc/headscale/acls.hujson

Create docker-compose.yml:

services:
  headscale:
    image: headscale/headscale:latest
    volumes:
      - headscale-data:/var/lib/headscale
      - ./config:/etc/headscale
    ports:
      - "8080:8080"
      - "9090:9090"
    command: serve
    restart: unless-stopped

volumes:
  headscale-data:
docker-compose up -d

Reverse Proxy with Nginx

Put headscale behind Nginx to handle SSL:

server {
    listen 443 ssl;
    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;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;

        # Required for Tailscale
        proxy_buffering off;
        proxy_read_timeout 3600;
        proxy_send_timeout 3600;
    }
}

Or use Caddy for automatic SSL:

headscale.yourdomain.com {
    reverse_proxy localhost:8080 {
        flush_interval -1
    }
}

Managing Users and Devices

Create a user (namespace)

headscale users create myname

Generate a pre-authentication key

headscale preauthkeys create --user myname --reusable --expiration 24h

This generates a key that devices use to register without interactive login.

Register a device

On the device you want to add:

# Linux
tailscale up --login-server https://headscale.yourdomain.com --authkey your-preauth-key

# Or interactive login (requires browser)
tailscale up --login-server https://headscale.yourdomain.com
# Then visit the shown URL to authenticate

The device appears in your headscale server and gets an IP from your configured prefix.

List and manage devices

headscale nodes list
headscale nodes delete --identifier 1
headscale routes list
headscale routes enable --route 192.168.1.0/24 --identifier 2

Subnet routing

To use headscale as a VPN gateway that exposes your home network:

  1. Enable IP forwarding on the server/router device
  2. Advertise the subnet:
    tailscale up --login-server https://headscale.yourdomain.com \
      --advertise-routes=192.168.1.0/24
    
  3. Enable the route:
    headscale routes enable --route 192.168.1.0/24
    

Now any device on your headscale network can reach 192.168.1.x through the advertising node.

ACL Policies

Control which devices can talk to which with ACL policies in /etc/headscale/acls.hujson:

{
  "acls": [
    {
      "action": "accept",
      "src": ["*"],
      "dst": ["*:*"]
    }
  ]
}

This default allows all devices to communicate. For more restrictive setups:

{
  "hosts": {
    "homelab": "100.64.0.1/32",
    "laptop": "100.64.0.2/32"
  },
  "acls": [
    {
      "action": "accept",
      "src": ["laptop"],
      "dst": ["homelab:22,443,80"]
    }
  ]
}

OIDC Authentication

For OIDC integration with Keycloak, Authentik, or other providers:

# In config.yaml
oidc:
  only_start_if_oidc_is_available: true
  issuer: https://auth.yourdomain.com/realms/master
  client_id: headscale
  client_secret: your-client-secret
  scope:
    - openid
    - profile
    - email
  extra_params:
    domain_hint: yourdomain.com
  allowed_domains:
    - yourdomain.com

With OIDC, users can log in with their existing SSO credentials — no need to create separate headscale accounts.

Headscale vs. Alternatives

Solution Pros Cons
Headscale Free, open source, full Tailscale client compatibility Self-hosted complexity, no Funnels/SSH
Tailscale No maintenance, excellent UX, all features Monthly cost, data on Tailscale's servers
WireGuard + wg-easy Maximum control, well-understood protocol Manual peer management, no auto-routing
Netbird Fully open-source coordination + clients Smaller ecosystem, newer
ZeroTier Excellent NAT traversal, free tier generous Proprietary control plane

Headscale is the right choice if you're already using Tailscale clients and want to eliminate the ongoing cost and data-sovereignty concerns.

Updating Headscale

With Docker Compose, updating is straightforward:

docker-compose pull headscale
docker-compose up -d

The database schema is automatically migrated on startup. Backup /var/lib/headscale/ before major version updates.

Get free weekly tips in your inbox. Subscribe to Self-Hosted Weekly