# Headscale + Headplane Standalone Stack This stack runs Headscale and Headplane on a single standalone Docker host. It is intended for the Headscale VM at `192.168.20.124`. ## Files - `headscale-compose.yml` - Docker Compose stack. - `headscale.env.example` - example environment file. Copy to `headscale.env` on the Docker host and fill in real values. - `headscale/config.yaml.example` - Headscale config template. Replace `@HEADSCALE_SERVER_URL@` during deployment. - `headscale/headplane-config.yaml.example` - Headplane config template. Replace URL placeholders during deployment. ## Persistent host paths Default paths from `headscale.env.example`: - `/opt/headscale/config` - Headscale config and DNS records file. - `/opt/headscale/data` - Headscale SQLite DB and generated keys. Back this up. - `/opt/headplane/config` - Headplane config. - `/opt/headplane/data` - Headplane state. - `/opt/headplane/secrets` - Runtime secret files. Do not commit these. ## Initial deployment shape - Headscale HTTP: host port `8080`, intended for Pangolin reverse proxy. - Headplane UI: host port `3000`, keep LAN/tailnet-only initially. - SQLite is used for Headscale. - ACL/policy file remains disabled initially; prove connectivity first, then harden. ## Validation ```bash docker compose --env-file headscale.env.example -f headscale-compose.yml config ``` If validating locally, Docker only renders the Compose model; it does not verify that the referenced `/opt/...` files already exist. ## Runtime secrets Do not commit runtime secrets. Generate these on the Docker host only: - `/opt/headplane/secrets/cookie_secret` - exactly 32 random characters for web session cookies. - `/opt/headplane/secrets/headscale_api_key` - generated with `docker exec headscale headscale apikeys create --expiration 90d`.