This repository provides a comprehensive setup for configuring Headscale with Caddy for reverse proxy and multiple admin web UIs for efficient management. The setup is based on the detailed guide available here.
- Automated Setup Script: Run a single script to configure everything
- Docker Network Configuration: Easily set up a Docker network for seamless communication between containers
- Caddy Integration: Secure and configure your Headscale instance with Caddy as the reverse proxy, including Basic Auth for additional security
- Headscale Configuration: Customize your Headscale setup with a simple configuration file
- Multiple Admin UIs: Three admin UI options for managing your Headscale instance
| UI | Path | Repository |
|---|---|---|
| Headscale UI | /web |
gurucomputing/headscale-ui |
| Headscale Admin | /hs-admin |
GoodiesHQ/headscale-admin |
| Headplane | /admin |
tale/headplane |
headscale-setup/
├── setup.sh # Automated setup script
├── compose.yaml # Main compose (includes all services)
├── compose.expose-localhost.yaml # Override to expose services on localhost
├── README.md
├── caddy/
│ ├── compose.yaml
│ └── container-config/
│ └── Caddyfile
├── headscale/
│ ├── compose.yaml
│ └── container-config/
│ └── config.yaml
└── admin-panel/
├── compose.yaml
└── container-config/
└── headplane.yaml
Run the setup script:
./setup.shThe script will:
- Create Docker network
reverseproxy-nw - Ask for your domain
- Ask for username and password (for Basic Auth)
- Generate password hash and configure Caddyfile
- Configure Headscale and Headplane
- Start all containers
- Generate and display an API key
# Install everything (default)
./setup.sh
# Skip Caddy installation (if you have your own reverse proxy)
./setup.sh --skip-caddy
# Skip all admin panels
./setup.sh --skip-admin
# Install only specific admin panels
./setup.sh --admin=headplane
./setup.sh --admin=headscale-ui,headplane
# Expose services on localhost (for SSH tunneling, etc.)
./setup.sh --expose-localhost
# Combine options
./setup.sh --skip-caddy --admin=headplane --expose-localhostAvailable admin panels: headscale-ui, headscale-admin, headplane
| Service | Port |
|---|---|
| headscale | 4000 |
| headscale-ui | 4020 |
| headscale-admin | 4021 |
| headplane | 4022 |
You can also use docker compose directly:
# Set DOCKER_GID for headplane docker socket access
export DOCKER_GID=$(getent group docker | cut -d: -f3)
# Start all services
docker compose up -d
# Start with localhost ports exposed
docker compose -f compose.yaml -f compose.expose-localhost.yaml up -d
# Start specific services
docker compose up -d caddy headscale headplaneThe setup script provides shortcuts for common headscale commands:
# Run any headscale command
./setup.sh headscale <command>
# Generate a new API key
./setup.sh apikey
# Generate password hash for Caddyfile
./setup.sh hash [password]
# Show help
./setup.sh helpExamples:
# List users
./setup.sh headscale users list
# List nodes
./setup.sh headscale nodes list
# Create a pre-auth key
./setup.sh headscale preauthkeys create --user default
# Create a new user
./setup.sh headscale users create myuser
# Generate password hash
./setup.sh hash mypasswordIf you're using Cloudflare for DNS, make sure to:
- Create an A record pointing your domain to your server IP
- Disable the proxy (orange cloud off / DNS only)
| Type | Name | Content | Proxy status |
|---|---|---|---|
| A | headscale | your.server.ip | DNS only (grey cloud) |
Important: Cloudflare proxy must be disabled because Headscale uses custom protocols that don't work through Cloudflare's proxy.
If you prefer manual configuration:
-
Create Docker Network:
docker network create reverseproxy-nw
-
Caddy Setup:
- Replace
domainwith your actual domain incaddy/container-config/Caddyfile - Generate password hash:
docker run --rm caddy:latest caddy hash-password --plaintext <password>
- Add your username and hashed password to the
Caddyfile
- Replace
-
Headscale Setup:
- Update
headscale/container-config/config.yamlwith your domain
- Update
-
Headplane Setup:
- Update
admin-panel/container-config/headplane.yamlwith your domain - Generate a 32-character cookie secret
- Update
-
Start Containers:
docker compose -f caddy/compose.yaml up -d docker compose -f headscale/compose.yaml up -d docker compose -f admin-panel/compose.yaml up -d
-
Generate API Key:
docker exec headscale headscale apikeys createUse this API key to authenticate in the admin UIs.
This project is licensed under the MIT License.