|
|
|
|
@@ -21,22 +21,26 @@ Self-hosted Headscale + Headplane pilot stack for replacing the Tailscale free-t
|
|
|
|
|
- `/mnt/docker-ssd/docker/appdata/headplane`
|
|
|
|
|
- No OIDC on day one
|
|
|
|
|
- No subnet-router or exit-node rollout on day one
|
|
|
|
|
- No public Pangolin exposure on day one
|
|
|
|
|
- Headscale can be published later as a dedicated public control-plane hostname without exposing Headplane the same way
|
|
|
|
|
|
|
|
|
|
## URLs for the pilot
|
|
|
|
|
|
|
|
|
|
- Headscale control plane: `http://headscale.home.paccoco.com:8084`
|
|
|
|
|
- Headplane UI: `http://headplane.home.paccoco.com:3005/admin`
|
|
|
|
|
- Headscale control plane for clients: `https://headscale.paccoco.com`
|
|
|
|
|
- Headplane admin UI (restricted/LAN-only): `http://headplane.home.paccoco.com:3005/admin`
|
|
|
|
|
|
|
|
|
|
These are the intended LAN/private-DNS endpoints for the pilot. If you later want Traefik/Pangolin exposure, use `examples/traefik-routes.yml` as a starting point instead of changing the pilot shape first.
|
|
|
|
|
This is the recommended **Option C** shape:
|
|
|
|
|
- publish **Headscale** on a stable public HTTPS hostname so phones and laptops can enroll/use it off-LAN
|
|
|
|
|
- keep **Headplane** off the public internet by default; treat it as an admin surface reached on LAN/private DNS (or a separately restricted admin path later)
|
|
|
|
|
|
|
|
|
|
The internal Traefik example in `examples/traefik-routes.yml` is still useful for private-DNS/LAN convenience, but it is not the public control-plane path for off-LAN device enrollment.
|
|
|
|
|
|
|
|
|
|
### Current live pilot note
|
|
|
|
|
|
|
|
|
|
The live PD pilot is currently using direct-IP URLs instead:
|
|
|
|
|
Before the public hostname is wired, the live PD pilot uses direct-IP URLs:
|
|
|
|
|
- Headscale: `http://10.5.30.6:8084`
|
|
|
|
|
- Headplane: `http://10.5.30.6:3005/admin`
|
|
|
|
|
|
|
|
|
|
Reason: the `home.paccoco.com` records for these pilot names have not yet been added in Technitium, and the current Technitium admin flow is 2FA-gated. Once those DNS records exist, flip the live stack back to the hostname-based URLs above.
|
|
|
|
|
Once `https://headscale.paccoco.com` is created and verified through Pangolin, off-LAN clients should use that public Headscale URL. Headplane can stay on the restricted LAN/private-DNS path above.
|
|
|
|
|
|
|
|
|
|
## Initial users
|
|
|
|
|
|
|
|
|
|
@@ -78,9 +82,15 @@ Before first deploy, replace the placeholder values in:
|
|
|
|
|
|
|
|
|
|
Required changes:
|
|
|
|
|
- replace `CHANGE_ME_TO_EXACTLY_32_CHARS` with a real 32-character cookie secret
|
|
|
|
|
- confirm the hostnames/IP-backed DNS records exist in Technitium
|
|
|
|
|
- confirm the restricted Headplane LAN/private-DNS record exists if you want the nicer admin hostname
|
|
|
|
|
- for off-LAN clients, create/verify the public Pangolin hostname for Headscale
|
|
|
|
|
- if you want different ports or hostnames, update both the config files and `.env`
|
|
|
|
|
|
|
|
|
|
Important live-ops note:
|
|
|
|
|
- the repo-tracked `config/headplane/config.yaml` intentionally keeps a placeholder `cookie_secret`
|
|
|
|
|
- before restarting the live Headplane container, render or restore the real 32-character secret from the live secret-bearing `.env`
|
|
|
|
|
- blindly syncing the tracked placeholder over the live config will make Headplane fail startup with `server.cookie_secret must be exactly length 32`
|
|
|
|
|
|
|
|
|
|
## Deploy on PD
|
|
|
|
|
|
|
|
|
|
1. Sync this directory into the live compose tree:
|
|
|
|
|
@@ -132,6 +142,26 @@ docker logs headplane --tail=100
|
|
|
|
|
11. Register one tagged service node.
|
|
|
|
|
12. Enroll one Manndra device.
|
|
|
|
|
|
|
|
|
|
## Public Headscale via Pangolin
|
|
|
|
|
|
|
|
|
|
For the off-LAN/mobile path, publish only Headscale itself.
|
|
|
|
|
|
|
|
|
|
Desired public hostname:
|
|
|
|
|
- `https://headscale.paccoco.com`
|
|
|
|
|
|
|
|
|
|
Desired Pangolin target shape:
|
|
|
|
|
- resource name: `headscale`
|
|
|
|
|
- site: `Plausible Deniability` (siteId `4`)
|
|
|
|
|
- target: `headscale:8080`
|
|
|
|
|
- healthcheck path: `/health`
|
|
|
|
|
- Pangolin auth/SSO: **disabled** for this route
|
|
|
|
|
|
|
|
|
|
Why:
|
|
|
|
|
- Headscale clients need a plain reachable control-plane endpoint; adding browser SSO in front of it is the wrong shape
|
|
|
|
|
- Headplane is an admin UI and should stay restricted/admin-only instead of being published like a normal household app
|
|
|
|
|
|
|
|
|
|
Use `automation/bin/pangolin_upsert_headscale.py` to create or reconcile the public Pangolin resource.
|
|
|
|
|
|
|
|
|
|
## Policy reload
|
|
|
|
|
|
|
|
|
|
After editing `config/headscale/policy.hujson`:
|
|
|
|
|
|