Self-Host Tailscale with Headscale

Khimananda Oli 8 min read Virtualization
Self-Host Tailscale with Headscale

By Khimananda Oli | Last reviewed: August 2026

You want the simplicity of Tailscale’s WireGuard mesh networking but cannot accept a third-party coordination server holding your network topology and user metadata. The solution is to self-host Tailscale with Headscale, an open-source implementation of the Tailscale control protocol that runs entirely on your own infrastructure. This approach gives you full data sovereignty, removes vendor lock-in, and allows operation in air-gapped or compliance-restricted environments where external SaaS dependencies are prohibited.

How does Headscale enable you to self-host Tailscale with Headscale?

Tailscale’s magic lies not in WireGuard itself—which is just encrypted UDP tunnels—but in the coordination server that handles key exchange, NAT traversal (DERP), and access policy distribution. When you self-host Tailscale with Headscale, you replace only this coordination layer. The actual data plane remains identical: standard Tailscale clients establish direct peer-to-peer WireGuard connections whenever possible, falling back to your self-hosted DERP relay only when direct paths fail.

Headscale ServerCoordination + APIPort 8080 / 9090PostgreSQLNode State + UsersSelf-Hosted DERPRelay + STUNFallback PathLaptopTailscale ClientVPS NodeTailscale ClientOffice LANSubnet RouterData Plane: Direct WireGuard P2P (no coordination server in path)Control Plane: Headscale manages keys, policies, and node discovery
Architecture overview when you self-host Tailscale with Headscale: coordination, state, relay, and direct peer connections

Understanding this separation is critical. Many engineers assume self-hosting means replacing the entire stack. In practice, you keep the battle-tested Tailscale client binaries on every endpoint. You gain sovereignty over metadata and policy without reimplementing complex NAT traversal logic. For teams managing hardened Ubuntu servers or compliance-bound infrastructure, this distinction matters: your audit scope covers the coordination server and DERP relay, not the WireGuard kernel module on every laptop.

What infrastructure do you need before deploying Headscale?

A common mistake is under-provisioning the coordination server. Headscale itself is lightweight, but its database backend determines reliability. For production use when you self-host Tailscale with Headscale, plan for these components:

  • Headscale server: 2 vCPU, 4 GB RAM minimum. Runs as a single binary or container. Exposes HTTP (8080) for client registration and gRPC/HTTPS (9090) for admin CLI.
  • PostgreSQL: Do not use SQLite in production. Concurrent node check-ins during outages cause write contention. A managed RDS instance or a properly tuned PostgreSQL deployment with streaming replication is strongly recommended.
  • DERP relay: At least one geographically close to your primary user base. If your team is in Nepal and India, a Mumbai or Singapore VPS provides better fallback latency than Frankfurt. Run at least two DERP nodes for redundancy.
  • TLS termination: Headscale requires HTTPS. Use Nginx or Caddy as a reverse proxy with valid certificates from Let’s Encrypt. Never expose raw HTTP to Tailscale clients.
  • DNS: A dedicated subdomain like headscale.yourdomain.com and derp.yourdomain.com. Avoid sharing with application domains to simplify certificate rotation and access control.

If you operate in an environment with strict egress filtering—common in Nepali government or financial sector deployments—ensure your firewall allows outbound UDP on arbitrary ports for WireGuard, plus TCP 443 for DERP fallback. Blocked UDP forces all traffic through DERP relays, destroying performance.

How do you install and configure Headscale step by step?

The following procedure assumes Docker Compose on Ubuntu 24.04 LTS. Adapt paths and versions for your environment. Always pin explicit image tags; never use latest in production.

Create the configuration file

Create /opt/headscale/config.yaml with your core settings. This is the most error-prone step—typos here silently break client enrollment.

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

db_type: postgres
db_host: localhost
db_port: 5432
db_name: headscale
db_user: headscale
db_pass: CHANGE_ME_USE_VAULT

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

oidc:
  issuer: https://auth.yourdomain.com
  client_id: headscale-prod
  client_secret: oidc-secret-from-vault
  allowed_domains:
    - yourdomain.com
  strip_email_domain: true

derp:
  server:
    enabled: false
  urls:
    - https://derp.yourdomain.com/derp/map
  auto_update_enabled: true
  update_frequency: 24h

log:
  format: json
  level: info

Store secrets in HashiCorp Vault or AWS Secrets Manager, not in plaintext YAML. Reference them via environment variables in your compose file. See Kubernetes secrets management done right for patterns that transfer directly to standalone deployments.

Deploy with Docker Compose

version: "3.9"
services:
  headscale:
    image: headscale/headscale:0.24.2
    command: serve
    ports:
      - "8080:8080"
      - "9090:9090"
    volumes:
      - ./config.yaml:/etc/headscale/config.yaml:ro
      - headscale-data:/var/lib/headscale
    environment:
      - HEADSCALE_DB_PASS=${DB_PASSWORD}
    restart: unless-stopped

  derp:
    image: fredliang/derper:latest
    ports:
      - "443:443"
      - "3478:3478/udp"
    environment:
      - DERP_DOMAIN=derp.yourdomain.com
      - DERP_CERT_MODE=letsencrypt
      - DERP_CERT_DIR=/app/certs
    volumes:
      - derp-certs:/app/certs
    restart: unless-stopped

volumes:
  headscale-data:
  derp-certs:

After starting, generate the initial admin API key: docker exec headscale headscale apikeys create --expiration 365d. Store this key securely—it cannot be retrieved later.

1. Generate Keyheadscale preauthkeyscreate --reusable2. Client Logintailscale up \--login-server=URL3. Approve Nodeheadscale nodes register--key <preauth>4. ConnectedNode receives peersDirect P2P establishedCLI Commands Reference# Create reusable pre-auth key for automated enrollmentheadscale preauthkeys create --user prod --reusable --expiration 30d# Register node manually (non-OIDC environments)headscale nodes register --user prod --key nodekey:abc123...# Verify connectivitytailscale status --json | jq '.PeerStatus[] | .Active'Common PitfallForgetting --login-server on EVERY client causes silent fallback to official Tailscale coord server.Set TAILSCALE_LOGIN_SERVER env var system-wide or use /etc/default/tailscaled to prevent drift.
Node enrollment sequence and CLI reference when you self-host Tailscale with Headscale

Enroll your first node

On each client machine, run:

tailscale up --login-server=https://headscale.yourdomain.com --accept-routes

This generates a node key and prints a registration URL. On the Headscale server, approve it:

headscale nodes register --user production --key <node-key-from-client-output>

For automated fleet enrollment, create reusable pre-authentication keys instead of approving each node manually. This is essential for CI runners, Kubernetes nodes, or any ephemeral infrastructure where manual approval doesn’t scale.

How does Headscale compare to official Tailscale for production use?

Choosing whether to self-host Tailscale with Headscale depends on your specific constraints. This comparison reflects real operational trade-offs observed across multiple production deployments in 2026.

CriteriaOfficial TailscaleHeadscale (Self-Hosted)
Data SovereigntyMetadata stored on Tailscale Inc. serversAll data stays on your infrastructure
Setup ComplexityZero-config, instantModerate: DB, TLS, DERP, OIDC required
High AvailabilityBuilt-in global redundancyYou design and maintain HA yourself
ACL Policy EngineFull HuJSON policy with groups, tags, testsSupported but less mature tooling
Admin UIPolished web consoleCommunity UIs exist; CLI-first by default
Compliance ScopeVendor SOC 2 report acceptedYour infra enters audit scope directly
Cost at ScalePer-user pricing adds up past ~50 usersFixed infra cost; marginal cost near zero
Offline / Air-GappedNot supportedFully functional without internet

The verdict is straightforward: if your organization has fewer than 30 users, no regulatory constraints, and values time-to-value over sovereignty, use official Tailscale. If you handle sensitive data subject to Nepal’s data residency expectations, operate in regulated sectors, exceed 100 users, or require air-gap capability, the operational investment to self-host Tailscale with Headscale pays for itself within months.

What monitoring and maintenance practices keep Headscale reliable?

Running the software is table stakes. Keeping it reliable requires observability. Headscale exposes Prometheus metrics on port 9090. Track these signals as part of your broader four golden signals framework:

  1. Registration latency: headscale_node_registration_duration_seconds. Spikes indicate database contention or TLS handshake failures.
  2. Failed authentications: headscale_auth_failures_total. Sudden increases signal OIDC misconfiguration or credential rotation issues.
  3. DERP relay utilization: Monitor bandwidth and concurrent connections on your DERP nodes. High sustained usage means UDP is blocked somewhere in your network path.
  4. Database connection pool saturation: Headscale opens many short-lived connections during sync bursts. Set max_open_conns appropriately and alert on pool wait time.

Back up PostgreSQL daily. Test restoration quarterly. Headscale state is small but irreplaceable—losing it means re-enrolling every node. Automate backups using the same patterns described in PostgreSQL backup and restore with pg_dump.

Start: Need Mesh VPN?Regulated Data / Air-Gap?YESNO>100 Users or Fixed Budget?Team <5 Engineers?YESNOYESNOSelf-Host HeadscaleSovereignty + Scale Justifies Ops CostUse Official TailscaleSpeed & Simplicity WinHybrid ApproachStart SaaS → Migrate LaterDecision framework for choosing between official Tailscale and self-hosting with Headscale in 2026
Decision flowchart: when to self-host Tailscale with Headscale versus using the managed service

Upgrade Headscale during maintenance windows only. Read release notes carefully—breaking changes in the control protocol can strand nodes until they’re re-enrolled. Maintain a staging environment that mirrors production topology to validate upgrades before touching live infrastructure.

Getting Started with Your Private Mesh Network

When you self-host Tailscale with Headscale correctly, you gain a sovereign, auditable mesh VPN that scales from home labs to multinational enterprises without per-seat licensing. Start with a single-node proof of concept using Docker Compose and SQLite to validate the workflow, then migrate to PostgreSQL and redundant DERP relays before onboarding production workloads. Document your enrollment procedures, automate backups, and integrate metrics into your existing observability stack from day one. If you need help designing a compliant, production-grade Headscale deployment tailored to your infrastructure constraints, reach out to discuss your architecture.

Frequently Asked Questions

Headscale is an open-source control server compatible with Tailscale clients. Self-hosting removes dependency on Tailscale’s coordination servers, keeps metadata private, and eliminates per-user licensing fees for large teams while retaining full mesh VPN functionality.

Yes. Official Tailscale clients for Linux, macOS, Windows, iOS, and Android work unmodified. You only replace the login server URL with your Headscale instance using the --login-server flag or configuration file.

A single vCPU, 1GB RAM, and 10GB storage suffice for under 500 nodes. PostgreSQL is recommended over SQLite for production. Run Headscale v0.23 or later behind a reverse proxy with valid TLS certificates.

Set the login server via tailscale up --login-server=https://headscale.example.com. On Linux, add this to /etc/default/tailscaled. Mobile apps require MDM profiles or manual config since they lack CLI flags for custom servers.

Yes. Headscale fully supports Tailscale ACL policies defined in hujson format. Define users, groups, tags, and rules in a policy file referenced by Headscale’s config.yaml to enforce granular network access controls.

Not directly. Nodes must be logged out from Tailscale’s official server and re-authenticated against your Headscale instance. Export node metadata beforehand for reference, but expect to re-register each device manually or via preauth keys.

Yes, for teams comfortable managing infrastructure. It lacks Tailscale’s managed reliability and support SLAs but is stable for internal use. Always run behind nginx or Caddy with automated certificate renewal and regular backups of the database.

Headscale respects Tailscale’s default 180-day key expiry. Configure disable_key_expiry in config.yaml to prevent disruptions. Preauth keys can be set to reusable or ephemeral. Rotate keys periodically and audit active sessions via the CLI.

Use PostgreSQL for production deployments exceeding 50 nodes or requiring high availability. SQLite works for testing or small setups but lacks concurrency safety. Ensure connection pooling is configured if using PgBouncer with Headscale.

Yes. Headscale supports OIDC authentication via config.yaml. Map provider claims to Tailscale users and groups automatically. This enables centralized identity management without maintaining separate credentials for VPN access across your organization.

Check tailscale status and tailscale debug netcheck on affected nodes. Verify DNS resolution of your Headscale domain, confirm TLS validity, and inspect Headscale logs for auth failures. Ensure firewall allows UDP 41641 and TCP 443.

Headscale is free and open-source. You pay only for hosting infrastructure. Tailscale charges per user beyond three free accounts. For 100 users, self-hosting saves thousands annually but adds operational overhead for maintenance and monitoring.

Yes. Configure custom DERP maps in Headscale’s config.yaml to route traffic through your own relays. This reduces latency and avoids Tailscale’s public DERP infrastructure. Deploy derper containers in strategic regions for optimal performance.

Cryptography remains identical since clients are unchanged. Risk shifts to your server hardening, TLS configuration, and access controls. Enable rate limiting, restrict admin API access, and keep Headscale updated to mitigate vulnerabilities absent in managed Tailscale.

Yes. Official container images exist for both platforms. In Kubernetes, use the community Helm chart with persistent volume claims for PostgreSQL. Mount config.yaml and policy files as ConfigMaps. Expose via Ingress with cert-manager for TLS.