Headscale is an open source, self-hosted replacement for the Tailscale control server. Your laptops, phones and servers keep running the normal Tailscale clients, but they log in to a coordination server you run instead of Tailscale's. It needs a public IP, HTTPS on port 443 and very little CPU, so the smallest VPS in an EU location is enough.
This post covers what Headscale replaces and what it does not, an install on a VPS with the official package, the ports, whether to run your own DERP relay, why the location of the coordination server matters under GDPR, and plan sizing. Commands and defaults come from the Headscale documentation for v0.29.7, released on 30 October 2026.
What does a Headscale server replace?
A Tailscale network has two halves. The data plane is WireGuard: devices encrypt traffic to each other directly, and private keys never leave the device. The control plane is a coordination server that registers devices, hands out their public keys and addresses, applies access rules and pushes DNS settings. Tailscale runs that server as a service; Headscale lets you run it yourself.
The feature list covers what most self-hosters use: registration by web login or pre-auth key, MagicDNS and split DNS, subnet routers and exit nodes, tags, ACLs and grants, Taildrop, Tailscale SSH, an embedded DERP relay and login through OpenID Connect. Not supported today: Funnel, Serve and network flow logs.
The project is explicit about scope. Its FAQ describes a single tailnet suitable for personal use or a small organisation, and says Headscale can likely handle hundreds of devices if little changes on the network. A large fleet of laptops that move between networks all day is where it starts to struggle. There is no web admin built in: you use the headscale command line, and the docs list community web interfaces such as Headplane if you want one.
Compared with a plain WireGuard server, the difference is topology. A WireGuard VPN server is a hub: every client tunnels to the VPS and out. With Headscale, devices connect to each other directly where they can, and the VPS only coordinates.
How do you install Headscale on a VPS?
The requirements are short: a public IP (dual stack recommended), HTTPS on port 443, a modern Linux or BSD system and a dedicated user. The recommended install is the official DEB package for Ubuntu 22.04 or newer or Debian 12 or newer, which creates the headscale user, a default config and a systemd unit:
HEADSCALE_VERSION="0.29.7"
HEADSCALE_ARCH="amd64"
wget --output-document=headscale.deb \
"https://github.com/juanfont/headscale/releases/download/v${HEADSCALE_VERSION}/headscale_${HEADSCALE_VERSION}_linux_${HEADSCALE_ARCH}.deb"
sudo apt install ./headscale.deb
Point a DNS name at the VPS, then set the essentials in /etc/headscale/config.yaml. Headscale can fetch its own Let's Encrypt certificate, and the packaged unit allows it to bind port 443:
server_url: https://hs.example.org
listen_addr: 0.0.0.0:443
metrics_listen_addr: 127.0.0.1:9090
grpc_listen_addr: 127.0.0.1:50443
tls_letsencrypt_hostname: hs.example.org
tls_letsencrypt_challenge_type: HTTP-01
database:
type: sqlite
dns:
magic_dns: true
base_domain: tailnet.example.org
The MagicDNS base_domain must differ from the server's own domain. SQLite is the recommended database; the example config calls PostgreSQL highly discouraged and kept only for legacy setups. Restart the service and check https://hs.example.org/health.
Then create a user and join a device:
sudo systemctl restart headscale
sudo headscale users create alice
# on the client:
tailscale up --login-server https://hs.example.org
# back on the server, with the auth ID the client printed:
sudo headscale auth register --user alice --auth-id AUTH_ID
For servers and scripts, headscale preauthkeys create makes a key that is valid for one hour and usable once by default. Clients must be Tailscale v1.80.0 or newer for this release. To share port 443 with other sites, put Caddy in front using the docs' reverse proxy example; Cloudflare's proxy and tunnels are not supported, because the Tailscale protocol needs WebSocket upgrades over POST.
Two habits from the FAQ: upgrade one minor version at a time without skipping, and do not join the Headscale VPS itself to the tailnet it controls, which the project does not support.
Which ports does Headscale need?
| Port | Protocol | Purpose | Open to |
|---|---|---|---|
| 22/tcp | SSH | Administration | Your IP only |
| 80/tcp | HTTP | Let's Encrypt HTTP-01 validation | Everyone, if you use the built-in certificate |
| 443/tcp | HTTPS | Control protocol, and DERP relay if enabled | Everyone |
| 3478/udp | STUN | NAT traversal for the embedded DERP server | Everyone, if DERP is enabled |
| 50443/tcp | gRPC | Remote control of Headscale from another machine | Closed unless you use it |
| 9090/tcp | HTTP | Metrics and debug | Never: keep on 127.0.0.1 |
ufw allow from 198.51.100.7 to any port 22 proto tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 3478/udp
ufw enable
A coordination server is a public HTTPS endpoint, and if it is unreachable, new devices cannot join and changes stop reaching your devices. Every Noded VPS includes 100 Gbps of always-on Layer 3/4 DDoS protection in front of it. Keep the host patched as well; our server hardening checklist is a good first hour.
Do you need your own DERP relay?
DERP relays carry traffic between two devices when they cannot reach each other directly, for example behind strict NAT or a firewall that blocks UDP. Out of the box, Headscale hands clients Tailscale's public DERP map, so relayed packets cross Tailscale's relay servers. The packets stay WireGuard-encrypted end to end, but the relay sees which IP addresses talk to it.
The embedded DERP server is off by default. Enabling it takes a few lines and adds your VPS to the map:
derp:
server:
enabled: true
stun_listen_addr: "0.0.0.0:3478"
verify_clients: true
ipv4: 203.0.113.10
urls: []
The empty urls list removes Tailscale's relays entirely, so all relayed traffic stays on your server. The docs warn that this makes your relay a single point of failure, so test with tailscale debug derp headscale before removing the defaults. Keep verify_clients on so only your devices can use the relay. The docs also note the embedded relay has no throughput optimisations: it exists to keep devices connected, not to carry heavy traffic.
Relayed traffic counts against the VPS's network ceiling. On our standard shapes that is a symmetric 100 to 300 Mbps per VM on a shared node port, with no transfer quota. For a homelab where most connections go direct, that is plenty.
Why run the coordination server in the EU?
The coordination server knows a lot about your network even though it never sees traffic: every device's name and operating system, which user owns it, the public IP addresses it connects from, when it was last online, your access rules and DNS names. With OpenID Connect login, it also holds names and email addresses from your identity provider. For a company, that is personal data about employees.
Running Headscale yourself decides where that data lives. Pick Bucharest or Sofia, both open for orders today, and the VPS, its disk and any images you capture stay in the EU under GDPR; Ashburn is in the United States. Our data processing agreement is part of the Terms, with nothing extra to sign, and the GDPR hosting page has the details. To keep relayed traffic in the EU as well, run the embedded DERP and drop Tailscale's map as above. This is a practical note, not legal advice: your own clients, logs and identity provider are part of the picture too.
Which Noded plan fits Headscale?
Headscale is light, and its docs publish no memory figure; we have not measured it either. Its load comes from recomputing the network map when devices change, so it scales with churn, not traffic. Prices are monthly, in euros, excluding VAT, from our live catalogue.
| Role | Plan | vCPU / RAM / SSD | Network | Bucharest | Sofia or Ashburn |
|---|---|---|---|---|---|
| Headscale for a homelab or small team | VPS I | 1 / 2 GB / 20 GB | 100 Mbps | €4 | €5.50 |
| Headscale plus embedded DERP for a busier tailnet | VPS II | 2 / 4 GB / 40 GB | 140 Mbps | €6 | €9 |
| Separate exit node or subnet router | VPS I or II | as above | 100 or 140 Mbps | €4 or €6 | €5.50 or €9 |
Run exit nodes on a second VPS, since the Headscale host should not join its own tailnet. If you want dual stack, as the requirements recommend, note that Bucharest is the location open today that includes free IPv6; Sofia and Ashburn are IPv4 only. Back up /var/lib/headscale, which holds the SQLite database and private keys, to another machine: our VPS plans have no snapshots or backups, and our restic and Borg post covers the target side.
Questions people ask
Is Headscale a self-hosted VPN?
It is the control half of one. Devices still use the Tailscale apps and WireGuard; Headscale replaces the hosted coordination service, so you get a self-hosted mesh VPN instead of a hosted VPN subscription.
How many devices can Headscale handle?
The project says likely hundreds, if the network is fairly static. Many devices that change networks constantly are the hard case, because every change recomputes the map for every node.
Can Headscale run at home instead of on a VPS?
It needs a public IP and HTTPS on port 443 reachable from everywhere your devices go. A VPS avoids depending on a home connection, a dynamic IP or carrier-grade NAT, and it keeps working when the house loses power.
Is Headscale the same as hosted VPN or VPN hosting?
No. A hosted VPN routes your traffic through a provider's servers. Headscale coordinates direct connections between your own devices, and traffic only crosses the VPS if you relay through DERP or use it as an exit node.
Running Headscale on Noded
Order VPS I in Bucharest or Sofia from the VPS hosting page, install the package, and join two devices before you move the rest. A tailnet is also a tidy way to keep SSH and admin panels of your other self-hosted services, such as the Owncast admin, off the public internet. If you also want a classic hub VPN for devices without the Tailscale app, the VPN hosting use case covers WireGuard and OpenVPN on the same kind of machine.