added headscale

This commit is contained in:
2026-05-28 15:57:26 -07:00
parent 760aa3e01e
commit 83e66b2116
4 changed files with 198 additions and 0 deletions
+105
View File
@@ -0,0 +1,105 @@
# Heascale
## Overview
Headscale is a self-hosted control server for Tailscale clients. It allows you to run your own private coordination plane for a WireGuard-based mesh network without relying on external SaaS services.
This deployment is designed to run fully self-hosted behind a reverse proxy.
Requires a valid config.yaml before first startup.
## Project Details
* Project Repository: https://github.com/juanfont/headscale
* Container Image: https://hub.docker.com/r/headscale/headscale
* Admin UI Image: https://hub.docker.com/r/goodieshq/headscale-admin
* Documentation: https://headscale.net/
* Reverse Proxy Domain: headscale.example.com
* Internal Service Port: 8080 (not exposed publicly)
* Environment Variable Notes
## Core Settings
These variables are used in the Docker Compose file (.env):
```
HEADSCALE_IMAGE Docker image for Headscale server (default: headscale/headscale:latest)
HEADSCALE_UI_IMAGE Docker image for admin UI
HEADSCALE_RESTART Restart policy (default: unless-stopped)
HEADSCALE_UI_RESTART Restart policy for UI container
# Paths
CONFIG_PATH Location of configuration files (config.yaml)
DATA_PATH Persistent database storage (SQLite)
LOG_PATH Application logs
# System
TZ Timezone (e.g. America/Vancouver)
HEADSCALE_LOG_LEVEL Logging verbosity (info, debug, etc.)
Domain Configuration
HEADSCALE_DOMAIN Public-facing domain used via reverse proxy
Example: headscale.4lt.ca
HEADSCALE_URL Full URL used by Headscale clients
Must match your reverse proxy domain:
```
## Volume Notes
All data is stored locally on the host for full self-sovereignty:
```
./config/headscale/config → Contains config.yaml (required configuration file)
./data/headscale → SQLite database and persistent Headscale state
./logs/headscale → Optional logs for debugging and monitoring
```
Back up data/ and config/ regularly for recovery.
## Network Notes
Uses a private Docker bridge network: internal
No public ports exposed directly
All access is routed through reverse proxy (NPM)
Reverse Proxy Requirements (Nginx Proxy Manager)
For headscale.example:
Forward hostname: headscale
Forward port: 8080
Scheme: http
Enable:
Websockets Support ✔
Block Common Exploits ✔
SSL (Lets Encrypt) ✔
Disable caching ✔
Additional Notes / Gotchas
Headscale will not function without a valid config.yaml
server_url inside config.yaml MUST match your domain.
Clients must explicitly point to your server:
tailscale up --login-server=https://headscale.4lt.ca
Do NOT expose port 8080 publicly — only via reverse proxy
SQLite is used by default (no external DB required)
Dockhand Stack, Deploy from Git
Cookbooks Repository
stackname: headscale
Compose file path:
headscale/compose.yaml
Additional env file (optional):
headscale/sample.env
Deployment Steps
Load sample.env into Dockhand environment variables
Ensure config.yaml exists in:
./config/headscale/config/config.yaml
Deploy stack
Configure reverse proxy in Nginx Proxy Manager
+51
View File
@@ -0,0 +1,51 @@
# Headscale Docker Compose Template
services:
headscale:
image: ${HEADSCALE_IMAGE:-headscale/headscale:latest}
restart: ${HEADSCALE_RESTART:-unless-stopped}
volumes:
- ${CONFIG_PATH:-./config}/headscale/config:/etc/headscale
- ${DATA_PATH:-./data}/headscale:/var/lib/headscale
- ${LOG_PATH:-./logs}/headscale:/var/log/headscale
- /etc/localtime:/etc/localtime:ro
environment:
- TZ=${TZ:-UTC}
- HEADSCALE_LOG_LEVEL=${HEADSCALE_LOG_LEVEL:-info}
expose:
- "8080"
networks:
- internal
command:
- headscale
- serve
user: "1000:1000"
headscale-ui:
image: ${HEADSCALE_UI_IMAGE:-goodieshq/headscale-admin:latest}
restart: ${HEADSCALE_UI_RESTART:-unless-stopped}
environment:
- TZ=${TZ:-UTC}
- HEADSCALE_URL=http://headscale:8080
expose:
- "80"
depends_on:
- headscale
networks:
- internal
networks:
proxy:
external: true
internal:
driver: bridge
+12
View File
@@ -0,0 +1,12 @@
server_url: https://headscale.example.com
listen_addr: 0.0.0.0:8080
db_type: sqlite3
db_path: /var/lib/headscale/db.sqlite
log:
level: info
dns_config:
override_local_dns: true
base_domain: tailnet.local
+30
View File
@@ -0,0 +1,30 @@
# =========================
# Headscale Configuration
# =========================
# Images
HEADSCALE_IMAGE=headscale/headscale:latest
HEADSCALE_UI_IMAGE=goodieshq/headscale-admin:0.26
# Restart policy
HEADSCALE_RESTART=unless-stopped
HEADSCALE_UI_RESTART=unless-stopped
# Paths
CONFIG_PATH=./config
DATA_PATH=./data
LOG_PATH=./logs
# Timezone
TZ=America/Vancouver
# Logging
HEADSCALE_LOG_LEVEL=info
# Domain (IMPORTANT)
HEADSCALE_DOMAIN=headscale.example.com
HEADSCALE_URL=https://headscale.example.com
# Ports (not exposed publicly, but useful for internal reference)
HEADSCALE_PORT=8080
HEADSCALE_UI_PORT=9090