headscale: add OIDC login, stop overriding clients' local DNS

Two changes to the control server, plus the fallout on the hosts.

OIDC via Authentik, so `tailscale up --login-server ...` opens a browser
instead of needing a pre-auth key. This is a second Authentik application,
separate from headplane's, with headscale's own /oidc/callback redirect.
Headless hosts keep using pre-auth keys. Note that headscale runs OIDC
discovery at startup and a failure is FATAL -- pointing `issuer` at an
application that does not exist yet means the control server will not
boot, so verify the discovery document before deploying.

override_local_dns = false, because the upstream default of true replaces
resolv.conf with 100.100.100.100 on every node. That silently broke the
LAN's `.sol` names -- pihole serves those and the global nameservers
return NXDOMAIN for them -- and took ad blocking down with them. It also
made each node's entire DNS depend on tailscaled, which is what had
forced --accept-dns=false onto neptun and mercury individually; both of
those workarounds are now removed, and with MagicDNS resolving properly
again neptun no longer needs its hardcoded /etc/hosts pin for jupiter.

Also serves jellyfin and seerr from jupiter, matching the ports they
already use on its LAN vhosts, and rotates the tailnet pre-auth keys.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-20 21:12:31 +02:00
co-authored by Claude Opus 4.8
parent d70df14c8a
commit 564dfb16b8
7 changed files with 87 additions and 62 deletions
+8 -3
View File
@@ -43,9 +43,14 @@
# placeholders (see services/vpn/headplane.nix) until Authentik/headscale are
# actually deployed and those get created for real.
#
# owner: unlike authentik's EnvironmentFile above, headplane opens these
# paths itself, already running as headscale's user — so root:root 0400
# would fail and each needs an explicit owner.
# owner: unlike authentik's EnvironmentFile above, headscale and headplane
# open these paths themselves, already running as the headscale user — so
# the root:root 0400 default would fail and each needs an explicit owner.
#
# headscale's OIDC client is a SEPARATE Authentik application from
# headplane's (services/vpn/headscale.nix), hence the second client secret.
sops.secrets.headscale_oidc_client_secret.owner = "headscale";
sops.secrets.headplane_cookie_secret.owner = "headscale";
sops.secrets.headplane_oidc_client_secret.owner = "headscale";
sops.secrets.headplane_headscale_api_key.owner = "headscale";