Add Keycloak IdP / SSO (ADR-0014, docs/15, R-IDP-*)
New identity subsystem, and resolves the C2 auth open question: - docs/15-identity-and-access.md + ADR-0014: Keycloak as central IdP; native OIDC where supported (Gitea, Nextcloud, Grafana, Kasm, Semaphore, Headlamp) and oauth2-proxy forward-auth for bare UIs (PiHole, *arr, qBittorrent, Homepage, Prometheus, Alertmanager, Hubble). Group-based authz + MFA; declarative realm/clients (GitOps); PostgreSQL on Longhorn, DR-critical + break-glass; hardened public exposure. Plex/Seerr use Plex auth; Minecraft N/A. - Requirements R-IDP-01..06; ServiceDefinition gains an block. - Onboarded early (with Gitea) so services adopt SSO as they come up. - Threaded through: docs 00,01,07,10,12,13; roadmap phases+workstreams; task board (T-6.1c/T-6.1d); glossary; ADR index; README. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This commit is contained in:
1 parent
1e0e67f902
commit
fb153f0bb5
14 files changed
+243
-14
No files matched your search
@@ -55,3 +55,4 @@ serves. **Do not edit an accepted decision in place** — supersede it with a ne
|
||||
| [0011](adr-0011-test-tooling-kyverno-chainsaw.md) | Conformance test tooling: Kyverno + Chainsaw | Accepted | R-TEST-01..05 |
|
||||
| [0012](adr-0012-vpn-egress-single-expressvpn-gateway.md) | VPN egress: single shared in-cluster ExpressVPN gateway | ~~Superseded by 0013~~ | R-NET-05/06/07 |
|
||||
| [0013](adr-0013-vpn-provider-pia-gluetun-wireguard.md) | VPN provider: PIA via Gluetun (WireGuard + port forwarding) | Accepted | R-NET-05/06/07 |
|
||||
| [0014](adr-0014-idp-keycloak.md) | Identity Provider: Keycloak (SSO via OIDC + forward-auth) | Accepted | R-IDP-01..06 |
|
||||
@@ -0,0 +1,45 @@
|
||||
# ADR-0014 — Identity Provider: Keycloak (SSO via OIDC + forward-auth)
|
||||
- Status: Accepted
|
||||
- Date: 2026-08-15
|
||||
- Serves: R-IDP-01, R-IDP-02, R-IDP-03, R-IDP-04, R-IDP-05, R-IDP-06
|
||||
- Supersedes: —
|
||||
|
||||
## Context
|
||||
The platform needs one identity and single sign-on: a central user directory, group-based
|
||||
authorization, MFA, and a way to protect both OIDC-capable apps and bare management UIs — without
|
||||
per-app passwords scattered across services. This also resolves the previously-open C2 auth question
|
||||
([12](../docs/12-command-center-ui.md)).
|
||||
|
||||
## Decision
|
||||
Use **Keycloak** as the platform IdP, integrated two ways behind one identity:
|
||||
- **Native OIDC** for apps that support it (Gitea, Nextcloud, Grafana, Kasm, Semaphore, Headlamp).
|
||||
- **Forward-auth proxy (oauth2-proxy → Keycloak)** at the Gateway for apps without usable OIDC
|
||||
(PiHole, *arr UIs, qBittorrent, Homepage, Prometheus, Alertmanager, Hubble UI).
|
||||
|
||||
Supporting decisions:
|
||||
- **Config as code**: realms/clients/groups are declarative and GitOps-reconciled (Keycloak Operator/
|
||||
Helm for the instance; `keycloak-config-cli` or realm-import for config). Secrets SOPS-encrypted.
|
||||
- **Authorization by groups**; **MFA** required for privileged groups.
|
||||
- **PostgreSQL on Longhorn**, DR-critical, backed up off-cluster; Keycloak rebuilds from DB + git.
|
||||
- **`public` exposure** (hardened) so login flows work for internet-exposed services.
|
||||
- **Exceptions**: Plex/Seerr use Plex auth; Minecraft uses Mojang/Microsoft; UniFi keeps native auth.
|
||||
|
||||
## Alternatives considered
|
||||
- **Authelia / Authentik** — lighter, and Authelia pairs cleanly with forward-auth; but Keycloak is
|
||||
the operator's explicit choice and offers the broadest OIDC/SAML, realm, and federation feature set
|
||||
for heterogeneous apps. (Chosen.)
|
||||
- **Per-app local auth only** — rejected: no SSO, password sprawl, weak central policy/MFA (fails
|
||||
R-IDP-01/06).
|
||||
- **Cloud IdP (e.g. hosted OIDC)** — rejected: this is a self-hosted, offline-capable home platform;
|
||||
identity should not depend on an external SaaS.
|
||||
|
||||
## Consequences
|
||||
- One login, one directory, central MFA and group policy; management UIs are never unauthenticated on
|
||||
the network (R-IDP-02).
|
||||
- **Keycloak becomes a critical dependency**: an IdP outage impairs SSO logins → DR-critical storage
|
||||
+ a documented **break-glass** local-admin path (e.g. on Gitea) so recovery tools stay reachable.
|
||||
- New platform components to run and secure: Keycloak, PostgreSQL, oauth2-proxy — all under
|
||||
default-deny with explicit allows and trusted TLS.
|
||||
- Onboarded **early** (with PiHole/Gitea) so later services integrate SSO as they come up.
|
||||
- Adds an `auth` block to the ServiceDefinition ([13](../docs/13-service-catalog.md)) so SSO mode +
|
||||
allowed groups are declarative per service.
|
||||
Reference in new issue
Block a user