Episode 15: Pocket ID as identity provider, tinyauth gate, offboarding script

Pocket ID replaces Forgejo as the OIDC provider for Outline, Vaultwarden and
NetBird; Forgejo logs in through it. Uptime Kuma sits behind tinyauth via
Caddy forward_auth (group ops), the public status page stays public.

offboarding/offboard.py switches one person off in every service with an API
and prints what a human still has to do: the shared passwords they could read.
Measured: SSO lock alone left 10 of 13 ways open for 45 minutes; the script
leaves 1 of 14, the vault copy on their laptop.

HARDENING.md: the ufw hairpin that broke Vaultwarden SSO and Kuma, the mesh
route into the docker bridges, and a fail2ban exception for Pocket ID.
This commit is contained in:
Maximilian Grimm 2026-09-23 11:52:17 +02:00
parent 3edef38ba3
commit 12542ecb19
9 changed files with 490 additions and 21 deletions

View file

@ -189,6 +189,20 @@ people. Note that joining is three steps, not two: you invite, they log in,
and then an owner has to **confirm** them. Until that confirmation, a member
sees no shared items at all.
## One identity provider, and an offboarding that ends at zero (Episode 15)
Since episode 15 everyone logs in through **Pocket ID** (`id.<DOMAIN>`, passkeys,
groups): Forgejo, Outline, Vaultwarden and NetBird are its OIDC clients, and
Uptime Kuma sits behind **tinyauth** (`auth.<DOMAIN>`) via Caddy `forward_auth`.
Group `staff` gets the apps, group `ops` gets the monitoring UI; the public status
page stays public. Both together need about 50 MB of RAM.
Switching someone off in the provider is not the same as offboarding them:
[`offboarding/`](offboarding/) has the numbers and the script that goes through
every service in about a second, and ends with the list of passwords a human
still has to change. The three firewall traps this uncovered are in
[HARDENING.md](HARDENING.md#episode-15-your-own-identity-provider-and-three-things-the-firewall-broke-quietly).
## Alerts that reach you (Episode 6)
A monitor nobody hears is a dashboard. Episode 6 adds a push channel you own