Skip to content

Gate Keycloak admin console via Cloudflare Access, excluding Keycloak as IdP

Date: 2026-07-02 Status: Accepted Decision: hl-cnyd Deciders: Sean (with Claude)

The Cloudflare tunnel routes id.fzymgc.house directly to keycloak-service, bypassing Traefik’s admin-allowlist Middleware entirely for internet traffic, leaving /admin and /realms/master completely ungated (hl-ba3a). Any fix establishes which system is the trust boundary/authenticator for the admin console on the public path, and must avoid a circular dependency since Keycloak is already the primary IdP for other Cloudflare Access applications in this account (docs, uptime_kuma).

Add a path-scoped Cloudflare Access Application on id.fzymgc.house/admin and /realms/master, authenticated via GitHub and Email-OTP identity providers, deliberately excluding Keycloak from allowed_idps. This establishes a standing rule: any Cloudflare Access Application fronting Keycloak’s own console must use a non-Keycloak IdP.

  • Keycloak cannot be its own gatekeeper — logging into Keycloak to reach the page that lets you log into Keycloak is circular
  • Narrow blast radius: new tf/cloudflare/access.tf resources only, no change to the tunnel or the OIDC back-channel (/realms/fzymgc/*) other apps depend on
  • Gives the operator a real, network-independent path to /admin instead of depending on LAN/Tailscale network topology
  • Cloudflare Access Application, GitHub + Email-OTP IdPs, path-scoped (chosen): narrow blast radius, network-independent admin path
  • Repoint the tunnel through Traefik (rejected): tunnel-relayed requests always present the cloudflared pod’s IP as RemoteAddr, so this would block ALL tunnel traffic to /admin without authenticating anyone; highest blast radius of any option — touches the OIDC back-channel Cloudflare Access itself depends on
  • NetworkPolicy (rejected): cannot do path-based gating; cloudflared legitimately needs L3/L4 access to keycloak-service:8443 for the OIDC back-channel regardless
  • Positive: the public tunnel path to /admin is no longer completely unauthenticated; operator gets a network-independent path to /admin
  • Negative: two identity checkpoints for admin access (Cloudflare Access, then Keycloak’s own login)
  • Neutral: reuses the existing docs_allow policy (domain-wide) rather than a tighter admin-specific policy — noted as a low-risk follow-up