Skip to main content

Identity and Keycloak

Keycloak 26.1.4 is the identity provider. It runs inside the cluster in the namespace startupos and is not reachable from the internet. The realm is startupos.

Sign-in and token validation. The frontend signs people in against Keycloak over the in-cluster address. Every one of the eight services validates access tokens against the same realm. The identity service also calls the Keycloak admin API. Keycloak stores its data in PostgreSQL.

Realm, clients and roles​

  • Realm roles: founder, mentor, admin, coordinator, cm_office. See Roles.
  • startupos-frontend: public client used by the frontend's own sign-in routes with the password grant.
  • startupos-backend: the original confidential client used by services for client-credentials calls. It is being replaced.
  • startupos-services: confidential client that replaces it. Its secret is generated, stored in the Secret startupos-oidc-client and read by secretKeyRef. See ADR 8.
  • identity-admin: confidential client with a service account that holds two realm-management roles, manage-users and view-realm. The identity service uses it to call the Keycloak admin API. It replaces a master-realm admin credential.

Tokens are issued with iss equal to http://keycloak:8080/realms/startupos, the in-cluster address, because the frontend calls Keycloak on that address. Every service is configured to accept that issuer. A token obtained through a public hostname would carry a different issuer and be refused.

High availability​

The manifest runs two Keycloak replicas. They cluster with Infinispan over jdbc-ping, which uses the shared database for discovery. A PodDisruptionBudget keeps one pod available, rolling updates never take a pod away before its replacement is ready, and a topology spread constraint places pods on different nodes.

Observed on 2026-11-07 (read-only): the Keycloak Deployment had 2 desired and 2 ready replicas, and a PodDisruptionBudget named keycloak-pdb existed. See ADR 7.

The PostgreSQL server that Keycloak depends on is a single replica, so Keycloak remains one database outage away from unavailable.

What happens if Keycloak is down​

Services start without Keycloak, because OIDC discovery is lazy. Public paths keep working. Protected paths fail closed with 401 or 500 and never open up. New sign-ins fail with 502. A failed refresh is treated as transient, so users are not signed out. A service that already holds Keycloak's signing keys keeps validating tokens. These behaviours come from a rehearsal and from code reading, not from a production outage test.

Sources: infra/k8s/keycloak.yaml, infra/keycloak/import-startupos-realm.sh, docs/runbooks/keycloak-fix-final-report.md, frontend/src/app/api/auth/session.ts, live Deployment and PodDisruptionBudget read on 2026-11-07.