feat: add headscale standalone compose stack
This commit is contained in:
70
headscale-compose.yml
Normal file
70
headscale-compose.yml
Normal file
@@ -0,0 +1,70 @@
|
||||
# Headscale + Headplane - Standalone Docker Compose Stack
|
||||
# Headscale: self-hosted Tailscale control server
|
||||
# Headplane: third-party Headscale web UI
|
||||
#
|
||||
# Usage:
|
||||
# cp headscale.env.example headscale.env
|
||||
# edit headscale.env
|
||||
# docker compose --env-file headscale.env -f headscale-compose.yml up -d
|
||||
#
|
||||
# Reverse proxy expectation:
|
||||
# - Proxy the public Headscale hostname to HEADSCALE_HTTP_PORT on this Docker host.
|
||||
# - Keep Headplane LAN/tailnet-only initially unless explicitly exposed later.
|
||||
|
||||
name: headscale
|
||||
|
||||
services:
|
||||
headscale:
|
||||
container_name: headscale
|
||||
image: headscale/headscale:${HEADSCALE_VERSION}
|
||||
restart: unless-stopped
|
||||
command: serve
|
||||
labels:
|
||||
# Required by Headplane's Docker integration so it can locate/restart Headscale.
|
||||
me.tale.headplane.target: headscale
|
||||
ports:
|
||||
# Headscale HTTP API / coordination endpoint. Intended for Pangolin reverse proxy.
|
||||
- "${HEADSCALE_HTTP_PORT}:8080"
|
||||
# Metrics/debug listener is bound to localhost in config by default; exposed only on Docker network.
|
||||
# gRPC is intentionally not published to the host for the initial setup.
|
||||
volumes:
|
||||
- ${HEADSCALE_CONFIG_DIR}/config.yaml:/etc/headscale/config.yaml:rw
|
||||
- ${HEADSCALE_CONFIG_DIR}/dns_records.json:/etc/headscale/dns_records.json:rw
|
||||
- ${HEADSCALE_DATA_DIR}:/var/lib/headscale:rw
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
healthcheck:
|
||||
test: ["CMD", "headscale", "version"]
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 5
|
||||
start_period: 30s
|
||||
networks:
|
||||
- headscale-net
|
||||
|
||||
headplane:
|
||||
container_name: headplane
|
||||
image: ghcr.io/tale/headplane:${HEADPLANE_VERSION}
|
||||
restart: unless-stopped
|
||||
depends_on:
|
||||
headscale:
|
||||
condition: service_started
|
||||
ports:
|
||||
# LAN/tailnet-only admin UI by default. Do not expose publicly until auth/proxy policy is reviewed.
|
||||
- "${HEADPLANE_HTTP_PORT}:3000"
|
||||
volumes:
|
||||
- ${HEADPLANE_CONFIG_DIR}/config.yaml:/etc/headplane/config.yaml:ro
|
||||
- ${HEADPLANE_SECRETS_DIR}:/run/secrets/headplane:ro
|
||||
- ${HEADPLANE_DATA_DIR}:/var/lib/headplane:rw
|
||||
# Shared Headscale config access enables Headplane network/DNS/config management.
|
||||
- ${HEADSCALE_CONFIG_DIR}/config.yaml:/etc/headscale/config.yaml:rw
|
||||
- ${HEADSCALE_CONFIG_DIR}/dns_records.json:/etc/headscale/dns_records.json:rw
|
||||
# Docker socket is read-only; Headplane uses it to find/restart Headscale after config changes.
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
networks:
|
||||
- headscale-net
|
||||
|
||||
networks:
|
||||
headscale-net:
|
||||
name: headscale-net
|
||||
driver: bridge
|
||||
Reference in New Issue
Block a user