Deploy Keycloak IdP to cluster (Phase 5a) #32

Closed
opened 2026-03-14 13:32:14 +00:00 by forgejo_admin · 0 comments

Lineage

plan-2026-03-08-tryout-prep → Phase 5 (Auth system — Keycloak IdP) → Phase 5a

Repo

forgejo_admin/pal-e-platform

User Story

As a platform operator
I want Keycloak deployed as a self-hosted identity provider on the cluster
So that all Pal-E apps can authenticate users via OIDC/OAuth2 without rolling their own auth

Context

Westside Basketball needs player/parent/coach auth for club operations (monthly payments, team rosters, player profiles). Rather than building auth into basketball-api, we're deploying Keycloak as a platform service — the same way Forgejo, Harbor, Woodpecker, and Ollama are deployed.

Decision: Keycloak was chosen over roll-your-own, magic links, or managed SaaS because it's enterprise-grade, self-hosted, OIDC standard, and reusable across all Pal-E apps. "Do it right, don't do it twice."

For Phase 5a, use the Bitnami Keycloak Helm chart with built-in PostgreSQL (not CNPG — migration to CNPG is a future concern). This matches how Harbor uses its internal database.

File Targets

Files to modify:

  • terraform/main.tf — add kubernetes_namespace_v1.keycloak, helm_release.keycloak, kubernetes_ingress_v1.keycloak_funnel
  • terraform/variables.tf — add keycloak_admin_password variable (sensitive, min 8 chars)
  • terraform/outputs.tf — optionally output keycloak URL

Files NOT to touch:

  • Salt pillar files — secrets management is a separate concern
  • Any other existing Helm releases

Acceptance Criteria

  • Keycloak namespace keycloak created
  • Bitnami Keycloak Helm chart deployed with built-in PostgreSQL
  • Tailscale funnel Ingress exposes Keycloak at keycloak.tail5b443a.ts.net
  • Admin password set via var.keycloak_admin_password (sensitive, type = "string")
  • Resource limits follow existing pattern (reasonable requests/limits)
  • Persistence enabled on local-path storage class
  • depends_on references Tailscale operator and ACL (same as all other funnels)
  • tofu fmt and tofu validate pass

Test Expectations

  • tofu plan shows 3 new resources (namespace, helm_release, ingress)
  • tofu validate passes
  • tofu fmt -check passes
  • Run: cd terraform && tofu fmt -check && tofu validate

Constraints

  • Follow the EXACT pattern of existing Helm releases in main.tf (namespace → helm_release → ingress with depends_on)
  • Use set_sensitive for admin password with type = "string" (not set)
  • Use oci://registry-1.docker.io/bitnamicharts/keycloak for the chart reference (Bitnami)
  • Chart version: use latest stable (check Bitnami registry)
  • External URL: https://keycloak.${var.tailscale_domain}/
  • Built-in PostgreSQL: postgresql.enabled = true in chart values (do NOT set up CNPG)
  • Resource limits: requests cpu = "100m", memory = "512Mi", limits memory = "1Gi" (Keycloak needs more memory than most services)
  • PostgreSQL resource limits: requests cpu = "50m", memory = "128Mi", limits memory = "512Mi"
  • Persistence: storageClass = "local-path", size = "2Gi" for Keycloak, "2Gi" for PostgreSQL
  • Ingress: funnel enabled (tailscale.com/funnel = "true"), TLS host = "keycloak"
  • Do NOT configure realms, clients, or users — that's Phase 5b

Checklist

  • PR opened with Closes #N
  • tofu plan output included in PR description
  • tofu fmt and tofu validate pass
  • No unrelated changes
  • project-westside-basketball — first consumer of Keycloak auth
  • plan-pal-e-platform — Keycloak may become a permanent platform service
### Lineage `plan-2026-03-08-tryout-prep` → Phase 5 (Auth system — Keycloak IdP) → Phase 5a ### Repo `forgejo_admin/pal-e-platform` ### User Story As a platform operator I want Keycloak deployed as a self-hosted identity provider on the cluster So that all Pal-E apps can authenticate users via OIDC/OAuth2 without rolling their own auth ### Context Westside Basketball needs player/parent/coach auth for club operations (monthly payments, team rosters, player profiles). Rather than building auth into basketball-api, we're deploying Keycloak as a platform service — the same way Forgejo, Harbor, Woodpecker, and Ollama are deployed. Decision: Keycloak was chosen over roll-your-own, magic links, or managed SaaS because it's enterprise-grade, self-hosted, OIDC standard, and reusable across all Pal-E apps. "Do it right, don't do it twice." For Phase 5a, use the Bitnami Keycloak Helm chart with built-in PostgreSQL (not CNPG — migration to CNPG is a future concern). This matches how Harbor uses its internal database. ### File Targets Files to modify: - `terraform/main.tf` — add `kubernetes_namespace_v1.keycloak`, `helm_release.keycloak`, `kubernetes_ingress_v1.keycloak_funnel` - `terraform/variables.tf` — add `keycloak_admin_password` variable (sensitive, min 8 chars) - `terraform/outputs.tf` — optionally output keycloak URL Files NOT to touch: - Salt pillar files — secrets management is a separate concern - Any other existing Helm releases ### Acceptance Criteria - [ ] Keycloak namespace `keycloak` created - [ ] Bitnami Keycloak Helm chart deployed with built-in PostgreSQL - [ ] Tailscale funnel Ingress exposes Keycloak at `keycloak.tail5b443a.ts.net` - [ ] Admin password set via `var.keycloak_admin_password` (sensitive, `type = "string"`) - [ ] Resource limits follow existing pattern (reasonable requests/limits) - [ ] Persistence enabled on `local-path` storage class - [ ] `depends_on` references Tailscale operator and ACL (same as all other funnels) - [ ] `tofu fmt` and `tofu validate` pass ### Test Expectations - [ ] `tofu plan` shows 3 new resources (namespace, helm_release, ingress) - [ ] `tofu validate` passes - [ ] `tofu fmt -check` passes - Run: `cd terraform && tofu fmt -check && tofu validate` ### Constraints - Follow the EXACT pattern of existing Helm releases in `main.tf` (namespace → helm_release → ingress with depends_on) - Use `set_sensitive` for admin password with `type = "string"` (not `set`) - Use `oci://registry-1.docker.io/bitnamicharts/keycloak` for the chart reference (Bitnami) - Chart version: use latest stable (check Bitnami registry) - External URL: `https://keycloak.${var.tailscale_domain}/` - Built-in PostgreSQL: `postgresql.enabled = true` in chart values (do NOT set up CNPG) - Resource limits: requests `cpu = "100m", memory = "512Mi"`, limits `memory = "1Gi"` (Keycloak needs more memory than most services) - PostgreSQL resource limits: requests `cpu = "50m", memory = "128Mi"`, limits `memory = "512Mi"` - Persistence: `storageClass = "local-path"`, size = "2Gi" for Keycloak, "2Gi" for PostgreSQL - Ingress: funnel enabled (`tailscale.com/funnel = "true"`), TLS host = "keycloak" - Do NOT configure realms, clients, or users — that's Phase 5b ### Checklist - [ ] PR opened with `Closes #N` - [ ] `tofu plan` output included in PR description - [ ] `tofu fmt` and `tofu validate` pass - [ ] No unrelated changes ### Related - `project-westside-basketball` — first consumer of Keycloak auth - `plan-pal-e-platform` — Keycloak may become a permanent platform service
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
forgejo_admin/pal-e-platform#32
No description provided.