Headscale

Open-source self-hosted Tailscale control server

Remote Access & VPN ★ 44.1k stars Medium setup BSD-3-Clause

Headscale is an open-source, self-hosted implementation of the Tailscale control server. It lets you run your own coordination server while using official Tailscale clients.

Headscale setup guides & articles

Hands-on coverage of Headscale from the blog.

Key features

  • Self-hosted Tailscale coordination
  • Works with official clients
  • Single binary server
  • ACL support

Pros & cons

Strengths

  • Full control of coordination
  • Lightweight

Trade-offs

  • No official GUI

Headscale replaces

Last reviewed Aug 25, 2026 · 722 words

Headscale makes your Tailscale network fully yours: a single Go binary reimplements the coordination server — the piece that authenticates devices and distributes keys — while every phone and laptop keeps running the official open-source Tailscale clients, just pointed at your URL. No device caps, no user tiers, no third party holding your network map. The deal, stated plainly up front: you are now operating the most security-critical service you own, and this guide is as much about that responsibility as about the (genuinely easy) setup.

Deploy: small server, public HTTPS, one config

Headscale wants a small always-on Linux box with a public HTTPS endpoint — a $5 VPS is the canonical home, since clients must reach it from anywhere. The container plus a config.yaml covers it: set server_url to your public https://headscale.example.com, leave SQLite as the database (correct at this scale), and put Caddy in front for TLS with websocket pass-through. RAM ~128 MB. Two config decisions worth making day one: enable MagicDNS with a base_domain so nodes get names, and decide your DERP posture (below). Then create a user and enroll each device by running the official client with --login-server https://headscale.example.com — desktop and CLI clients take the flag directly; iOS and Android accept an alternate server in the app settings. Pre-auth keys (headscale preauthkeys create) enroll servers non-interactively, which is how your containers and boxes join without ceremony.

The pieces you're now responsible for

  • The database is your network. /var/lib/headscale (SQLite) holds every node registration; lose it and every device re-enrolls by hand. It goes in the nightly backup, and the restore gets tested like anything else that matters.
  • Updates are security events. A coordination-server vulnerability is a network-wide problem; watch Headscale releases (it tracks a moving upstream, so client/server version drift occasionally breaks features first) and patch deliberately rather than automatically.
  • The admin surface is the crown jewels. The headscale CLI on the server and the gRPC API can mint pre-auth keys — i.e., add devices to your network. Keep the API loopback-only unless you consciously need remote admin; if you add one of the community web UIs, treat its authentication as seriously as the threat model demands, because "admin panel for adding devices to my VPN" is not a thing to put behind a weak password.

DERP: borrow Tailscale's relays or run your own

When NAT traversal fails, traffic falls back to DERP relays. Headscale defaults to using Tailscale's public DERP fleet — encrypted ciphertext only, but a dependency on the company you were routing around. Your call: leaving it is pragmatic (their relay network is global and excellent), while derp.server.enabled: true runs Headscale's embedded DERP for full independence — at the cost of your VPS relaying those sessions' bandwidth, the same arithmetic as a RustDesk relay. Most self-hosters sensibly start on the public relays and revisit if principle or traffic patterns demand.

ACLs: the same policy engine, in a file you own

Headscale implements Tailscale's ACL policy format — JSON (HuJSON) defining who reaches what, with tags for servers and groups for people. Write it early, exactly as the Tailscale guide argues: a flat everything-reaches-everything network is fine at five devices and a liability at twenty-five. The file lives on your server (policy.path), versions in git, and reloads without restarts — config-as-code for your network's firewall, which is precisely the sort of thing that makes the self-hosted control plane worth its keep. Subnet routers and exit nodes work as upstream: advertise from the client, approve with headscale routes.

What I'd do

Headscale on a dedicated small VPS with Caddy, SQLite backed up nightly and restore-tested, MagicDNS on, public DERP accepted initially, ACLs in git from device ten, API loopback-only with no web UI, releases watched and patched within the week. And a candor note this directory owes you: hosted Tailscale with tailnet lock is the better answer for people who won't sustain that list — Headscale is the right choice exactly when you read it and nodded rather than sighed.

Compare Headscale

9 head-to-head comparisons.

Similar remote access & vpn apps