PROJECT(1) PROJECT(1)
NAME
Self-hosted Tailscale with Headscale
Replacing the Tailscale control plane with a self-hosted alternative for complete network sovereignty
SYNOPSIS
Date: December 19, 2025
Status: Complete
Tags: [Networking] [Docker] [VPN] [Self-hosted]
DESCRIPTION
Self-hosted Tailscale with Headscale
Tailscale is great, but trusting a third party with your network topology felt wrong. Enter Headscale - an open-source implementation of the Tailscale control server.
Why Self-host?
- Privacy: No third party sees your network structure
- Control: Full access to the coordination server
- Learning: Understanding WireGuard and DERP servers
- Permanence: Not dependent on a company’s business decisions
The Setup
Running on a small VPS with a public IP:
# docker-compose.yml
version: '3.8'
services:
headscale:
image: headscale/headscale:latest
container_name: headscale
restart: unless-stopped
volumes:
- ./config:/etc/headscale
- ./data:/var/lib/headscale
ports:
- "8080:8080"
- "9090:9090"
command: serve
Configuration
The config.yaml needs a few key settings:
server_url: https://headscale.yourdomain.com
listen_addr: 0.0.0.0:8080
grpc_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:
- 100.64.0.0/10
dns:
base_domain: tail.net
nameservers:
global:
- 1.1.1.1
Client Registration
Creating a user and pre-auth key:
# Create a user namespace
docker exec headscale headscale users create homelab
# Generate a pre-auth key
docker exec headscale headscale preauthkeys create \
--user homelab \
--reusable \
--expiration 24h
Then on the client:
tailscale up --login-server=https://headscale.yourdomain.com \
--authkey=YOUR_PREAUTHKEY
DERP Relay
For NAT traversal, I’m running my own DERP server. This ensures traffic never touches third-party relay servers:
regions:
900:
regionid: 900
regioncode: home
regionname: Home Lab
nodes:
- name: home-derp
regionid: 900
hostname: derp.yourdomain.com
ipv4: YOUR_PUBLIC_IP
stunport: 3478
derpport: 443
Results
All 15 devices across 3 locations now communicate through my own control plane. The coordination server runs on a $5/month VPS and handles everything perfectly.
No more third-party involvement in my network topology.