Skip to content

hwdsl2/docker-headscale

Repository files navigation

English | 简体中文 | 繁體中文 | Русский

Headscale Server on Docker

Build Status

A Docker image to run a Headscale server — a self-hosted, open-source implementation of the Tailscale coordination server. Connect all your devices using the official Tailscale client apps, with your own server in control.

Also available: Docker images for WireGuard, OpenVPN, and IPsec VPN.

Download

Get the trusted build from the Docker Hub registry:

docker pull hwdsl2/headscale-server

Alternatively, you may download from Quay.io:

docker pull quay.io/hwdsl2/headscale-server
docker image tag quay.io/hwdsl2/headscale-server hwdsl2/headscale-server

Quick Start

Prerequisite

A publicly reachable server with a domain name and TLS certificate is strongly recommended. See TLS and reverse proxy for setup options.

Using Docker

Create an environment file. See Environment variables for details.

# Edit the env file and set HS_SERVER_URL at minimum
cp vpn.env.example vpn.env
nano vpn.env

Run the container:

docker run \
  --name headscale \
  --restart=always \
  -p 8080:8080/tcp \
  -v headscale-data:/var/lib/headscale \
  -v ./vpn.env:/vpn.env:ro \
  -d hwdsl2/headscale-server

On first start, the container will:

  1. Generate the server configuration from your environment variables
  2. Create the initial user (default: admin)
  3. Print a reusable pre-auth key to the container logs

Retrieve the initial pre-auth key from the logs:

docker logs headscale

Connect a device using the official Tailscale client:

tailscale up --login-server https://hs.example.com --authkey <key-from-logs>

Using Docker Compose

cp vpn.env.example vpn.env
nano vpn.env        # Set HS_SERVER_URL at minimum
docker compose up -d
docker compose logs headscale

Example docker-compose.yml (already included):

services:
  headscale:
    image: hwdsl2/headscale-server
    container_name: headscale
    restart: always
    ports:
      - "8080:8080/tcp"
    volumes:
      - headscale-data:/var/lib/headscale
      - ./vpn.env:/vpn.env:ro

volumes:
  headscale-data:

Managing the server

Use the hs_manage helper to manage users and nodes from the host without entering the container.

List users:

docker exec headscale hs_manage --listusers

Add a user:

docker exec headscale hs_manage --adduser alice

Create a pre-auth key for a user:

docker exec headscale hs_manage --createkey --user alice

List all registered nodes:

docker exec headscale hs_manage --listnodes

List nodes for a specific user:

docker exec headscale hs_manage --listnodes --user alice

Delete a node by ID:

docker exec headscale hs_manage --deletenode 3
# Or skip the confirmation prompt:
docker exec headscale hs_manage --deletenode 3 --yes

List all pre-auth keys:

docker exec headscale hs_manage --listkeys

Show help:

docker exec headscale hs_manage --help

Environment variables

All variables are optional. HS_SERVER_URL is strongly recommended for production use.

Variable Default Description
HS_SERVER_URL auto-detected URL that Tailscale clients connect to (e.g. https://hs.example.com). Must be HTTPS for full client functionality.
HS_LISTEN_PORT 8080 TCP port the server listens on.
HS_METRICS_PORT 9090 Prometheus metrics port. Set to empty to disable.
HS_BASE_DOMAIN headscale.internal Base domain for MagicDNS hostnames (e.g. myhost.headscale.internal). Must not equal or be a parent domain of the hostname in HS_SERVER_URL (e.g. if HS_SERVER_URL=https://hs.example.com, do not use example.com).
HS_USERNAME admin Name of the first user created on initial setup.
HS_DNS_SRV1 1.1.1.1 Primary DNS server pushed to clients via MagicDNS. Accepts IPv4 or IPv6.
HS_DNS_SRV2 1.0.0.1 Secondary DNS server pushed to clients via MagicDNS.
HS_LOG_LEVEL info Log verbosity: panic, fatal, error, warn, info, debug, trace.

The configuration file is regenerated on each container start. To change a setting, update vpn.env and restart the container. The env file is bind-mounted into the container, so changes are picked up on every restart without recreating the container.

TLS and reverse proxy

Tailscale clients work best with HTTPS. The recommended setup is to run a reverse proxy in front of Headscale that handles TLS termination, then set HS_SERVER_URL to your HTTPS URL.

Example with Caddy (automatic TLS via Let's Encrypt):

Caddyfile:

hs.example.com {
  reverse_proxy headscale:8080
}

Example with nginx:

server {
  listen 443 ssl;
  server_name hs.example.com;

  ssl_certificate     /path/to/cert.pem;
  ssl_certificate_key /path/to/key.pem;

  location / {
    proxy_pass http://127.0.0.1:8080;
    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;
    proxy_read_timeout 3600s;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

Set HS_SERVER_URL=https://hs.example.com in your vpn.env and restart the container.

Ports to open in your firewall:

Port Protocol Purpose
8080 TCP Headscale coordination server (or your reverse proxy port)
443 TCP HTTPS (if using a reverse proxy)
9090 TCP Prometheus metrics (optional, internal use only by default)

Update Docker Image

To update the Docker image and container, first download the latest version:

docker pull hwdsl2/headscale-server

If the Docker image is already up to date, you should see:

Status: Image is up to date for hwdsl2/headscale-server:latest

Otherwise, it will download the latest version. Remove and re-create the container using instructions from Quick Start. Your data is preserved in the headscale-data volume.

License

Note: The software components inside the pre-built image (such as Headscale) are under the respective licenses chosen by their respective copyright holders. As for any pre-built image usage, it is the image user's responsibility to ensure that any use of this image complies with any relevant licenses for all software contained within.

Copyright (C) 2026 Lin Song Creative Commons License
This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.

Headscale is Copyright (c) 2020, Juan Font, and is distributed under the BSD 3-Clause License.

Tailscale® is a registered trademark of Tailscale Inc. This project is not affiliated with or endorsed by Tailscale Inc.

About

Docker image to run a Headscale server — a self-hosted, open-source mesh VPN coordination server. Connect all your devices with your own server in control, using the official Tailscale client apps.

Topics

Resources

License

Stars

Watchers

Forks