From 4fb4297e12b401dc3de1d4fc5b72ce41f1fe4aa4 Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Mon, 20 Jul 2026 21:31:50 +0200 Subject: [PATCH] README: refresh post-deploy steps after the DNS and OIDC changes The jupiter /etc/hosts pin step is gone: headscale no longer overrides clients' local DNS, so MagicDNS resolves that name properly and the hardcoded tailnet address is no longer needed. Replaces it with the headscale OIDC application, including the warning that discovery failure at startup is fatal, and that OIDC users cannot be reconciled with CLI-created ones -- 0.28 dropped both map_legacy_users and node reassignment, so switching a node's owner means re-enrolling it. Documents the Authentik admin swap: superuser is a group flag, and akadmin must be deactivated rather than renamed or deleted, since the bootstrap blueprint keys on the username and recreates it otherwise. For mercury, records that a reflash wipes the gravity database along with the adlists -- resolution keeps working with nothing blocked, which is easy to miss -- and that .sol not resolving on mercury itself is by design, while it resolving on tailnet members depends on override_local_dns staying false. Co-Authored-By: Claude Opus 4.8 --- README.md | 47 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index ff9b71c..6f42dec 100644 --- a/README.md +++ b/README.md @@ -142,6 +142,12 @@ another way in. `https://auth.mgaction.town` with `authentik_bootstrap_password` from sops. The username is hardcoded upstream and the bootstrap runs once — later changes to the env vars are ignored. + To use your own admin instead: create a user, add it to the **`authentik + Admins`** group (superuser is a *group* flag in Authentik, there is no + per-user one), verify it works in a private window, then **deactivate** + `akadmin` — do not rename or delete it. The bootstrap blueprint keys on + `username: akadmin` with `state: created`, so if no user by that name + exists it simply makes a new one on the next reconcile. 3. **Bootstrap the tailnet** (headscale starts with an empty database): ``` sudo headscale users create darman @@ -159,10 +165,23 @@ another way in. application with slug **`headplane`** — the slug is what makes the issuer `.../application/o/headplane/` in `services/vpn/headplane.nix`. Client ID goes in that file, client secret into sops. -6. **Pin jupiter's tailnet address.** `networking.hosts` in - `hosts/neptun/configuration.nix` carries jupiter's IP, because neptun runs - `--accept-dns=false` and cannot use MagicDNS. Until it matches - `headscale nodes list`, the `abs.` and `git.` vhosts fail to proxy. +6. **Headscale OIDC** (optional — pre-auth keys work without it). A *second* + Authentik provider/application, slug **`headscale`**, redirect + `https://vpn.mgaction.town/oidc/callback` (headscale's own, not headplane's + under `/admin`). Client ID in `services/vpn/headscale.nix`, secret into sops + as `headscale_oidc_client_secret`. + ⚠️ headscale runs OIDC discovery **at startup and a failure is fatal** — + an issuer pointing at an application that doesn't exist yet means the + control server won't boot, taking the whole tailnet's control plane with + it. Always verify first: + ``` + curl -s https://auth.mgaction.town/application/o/headscale/.well-known/openid-configuration + ``` + Users created by OIDC login are distinct from `headscale users create` + ones: headplane matches the OIDC `sub` claim against the user's + `providerId`, CLI-made users have none, and 0.28 dropped both + `map_legacy_users` and node reassignment — so moving an existing node to + an OIDC user means re-enrolling it. ### jupiter @@ -190,9 +209,23 @@ another way in. ``` sudo nix-store --verify --check-contents # add --repair to fix ``` - A card that has corrupted one path will corrupt more. Replace it and reflash; - only pihole's runtime state (query history, dynamic leases) is lost — the - static leases are declarative. + A card that has corrupted one path will corrupt more. Replace it and reflash. +- **A reflash wipes `/var/lib/pihole`**, which is NOT declarative. The + `FTLCONF_*` env vars rebuild the DNS/DHCP config, but the gravity database + goes with it — so adlists and blocking are gone and resolution silently + keeps working with nothing blocked (`Blocked DNS queries: 0` in the logs is + the tell). Re-add the adlists, then: + ``` + sudo podman exec pihole pihole -g + ``` +- mercury's own `resolv.conf` is deliberately public resolvers, not its own + pihole (`resolveLocalQueries = false`, see `CLAUDE.md`) — so `.sol` names do + not resolve *on mercury itself*. That is expected, not a fault. +- LAN `.sol` names resolve on tailnet members only because headscale sets + `override_local_dns = false`. With upstream's default of `true`, every node's + `resolv.conf` is replaced with MagicDNS and `.sol` returns NXDOMAIN + everywhere — along with losing ad blocking, since queries stop reaching + pihole at all. ## Adding a service