Skip to main content

Overview

Keycloak is an open-source identity and access management platform that provides single sign-on, OIDC/SAML, user federation, and fine-grained authorization. This template runs clustered Keycloak 26 in production mode with a highly available PostgreSQL backing store by default, delivering zero-downtime restarts and upgrades.

What Gets Created

  • Stateful Keycloak Workload — 2 replicas by default, clustered via embedded Infinispan (JGroups JDBC_PING through the shared database — no extra clustering infrastructure). Setting replicas: 1 runs a dev mode with clustering fully disabled.
  • Highly Available PostgreSQL Stack (default) — The PostgreSQL Highly Available template as a subchart: 3 Patroni PostgreSQL replicas, 3 etcd replicas, and an HAProxy leader-routing workload that Keycloak connects through.
  • Single-Instance PostgreSQL Workload (optional) — The PostgreSQL template instead, for lighter dev/test deployments.
  • Volume Sets — Persistent storage for the PostgreSQL (and etcd) data.
  • Backup Cron Workload (optional) — Created by the backing store subchart when its backup pass-through is enabled.
  • Secrets — An opaque startup script secret, plus the database credentials secret created by the PostgreSQL subchart. The bootstrap admin credentials are not created by this template: you create that dictionary secret yourself before installing and reference it by name (see Prerequisites).
  • Identity & Policy — An identity bound to the Keycloak workload with a least-privilege policy granting reveal access to exactly the secrets it mounts.
All durable state — realms, users, and active sessions — lives in PostgreSQL; the Keycloak tier is stateless on disk.
This template does not create a GVC. You must deploy it into an existing GVC.

Prerequisites

One dictionary secret must exist before you install. The bootstrap admin guards a login form on the public endpoint, so its credentials are a prerequisite secret rather than template values — a value would sit in plaintext in the Helm release for the life of the install. The template creates no admin secret of its own.
1

Create the admin credentials secret

A dictionary secret holding exactly the keys username and password. Secrets are org-level, so no GVC flag is involved:
Set admin.secretName to the name you used.
2

Read the password back later

-o yaml is required; without it the command prints the secret’s metadata table rather than its contents:
A missing prerequisite secret wedges the install rather than failing it. The install still exits 0 and reports success, every resource is created, and the workload then never starts. Because the container never ran, cpln logs returns zero lines, which reads as a broken platform rather than a missing prerequisite.The only diagnostic is status.versions[].message, which names the missing secret:
It is get-deployments — plain cpln workload get has no versions key at all. Creating the missing secret clears the wedge on its own, but slowly: recovery has measured between 5.5 and 10.5 minutes across the catalog, so poll rather than giving up. cpln workload force-redeployment RELEASE_NAME-keycloak --gvc GVC_NAME shortcuts it to roughly 90 seconds.
If you enable the optional database backups, you need a cloud account and a bucket for the backing store’s backup job. The backup configuration is a pass-through to the backing PostgreSQL template — follow the PostgreSQL Highly Available backup prerequisites (default store) or the PostgreSQL backup prerequisites (dev/test store).

Installation

To install, follow the instructions for your preferred method:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Upgrading From 1.0.x

Version 1.1.0 moved the bootstrap admin login out of Helm values. Earlier versions shipped a username and a working password as values, used exactly as written — a published default guarding a login form on the public endpoint, sitting in the Helm release for the life of the install.
An upgrade that still carries either removed key is rejected at render, before anything is applied. Each guard names its replacement, and there is no compatibility fallback — the version bump is the migration path. A real upgrade carrying an old key failed at render, created no Helm revision, and left the running release healthy and untouched:
Leaving admin.secretName empty is refused the same way.
An existing install’s admin password does not change on upgrade. Keycloak consults KC_BOOTSTRAP_ADMIN_* only when no admin account exists yet, so the account already in the database is untouched by whatever the secret holds. Create the secret so the release renders, then change the password in the Keycloak admin console. If the install is still carrying the published 1.0.x default (change-me-keycloak-admin), treat that password as compromised and change it in the console now.
To upgrade an existing install:
1

Create the admin credentials secret

Follow Prerequisites. Putting your current credentials in it keeps your values file honest, but it does not re-seed the account.
2

Drop the removed keys from your values

Remove admin.username and admin.password, and set admin.secretName instead.
3

Upgrade

Realms, users, and sessions are in PostgreSQL and are untouched. The Keycloak replicas restart — see Replicas and Clustering.

Configuration

The default values.yaml for this template:

Replicas and Clustering

  • replicas2 or more (default) runs Keycloak in a cluster: the replicas form an Infinispan cluster over JGroups JDBC_PING through the shared database, so restarts and upgrades are zero-downtime and in-flight logins and sessions survive a replica restart. 1 runs a dev mode with clustering fully disabled (local cache only).
  • Clustered replicas must be able to reach each other on ports 7800/57800, so replicas > 1 requires internalAccess.type other than none — the chart enforces this at render.
  • Scaling is operator-driven: change replicas via a template upgrade. There is deliberately no autoscaling, so cluster membership only changes intentionally.
A rolling upgrade is not constrained to one replica at a time. Control Plane silently discards maxUnavailableReplicas on stateful workloads, so version 1.1.0 stopped declaring it and now renders only what the platform actually applies — nothing limits how many replicas restart together. Realms, users, and sessions live in PostgreSQL and survive regardless, but plan for a brief gap in availability during an upgrade rather than assuming a strictly serialized rollout.

Keycloak Resources

  • resources — CPU and memory per replica. The JVM heap is sized to 70% of the memory limit; do not set memory below 1.5Gi.

Admin Bootstrap

  • admin.secretName — Name of the dictionary secret you created in Prerequisites, holding the username and password of a temporary bootstrap admin. The credentials never pass through values, and the template creates no secret of its own — it references yours and grants the workload reveal on exactly that one secret.
  • The account is created on first boot only. Keycloak reads those credentials when no admin exists yet, so editing the secret on a running install changes nothing — change the password in the admin console instead.
  • After the first login, create a permanent admin account and remove the temporary one — Keycloak warns until you do.

Backing Store

Exactly one of the two stores must be enabled — the chart enforces this at render.
  • postgresHA (default) — A highly available PostgreSQL cluster from the PostgreSQL Highly Available template: 3 Patroni replicas, 3 etcd replicas, and an HAProxy endpoint that routes Keycloak’s connections to the current leader. Do not disable the HA proxy (postgresHA.proxy.enabled) — Keycloak writes through the HAProxy leader endpoint, and the chart enforces this at render.
  • postgres — A single-instance PostgreSQL from the PostgreSQL template, for lighter dev/test deployments. Set postgresHA.enabled: false and postgres.enabled: true.
  • postgresHA.postgres.* / postgres.credentials.* — Database credentials and database name. Change the password before installing.
  • postgresHA.volumeset.capacity / postgres.volumeset.capacity — Initial volume size in GiB (minimum 10, per replica for the HA store).
Template version 1.0.0 did not compact the etcd cluster inside the bundled highly available database, so etcd’s backend grows with time alone and goes read-only once it reaches its 2 GiB quota — after roughly 110 days — taking PostgreSQL failover with it. Only installs running the HA database are affected (postgresHA.enabled, the default here); see etcd History Compaction for the mechanism and the symptoms. Upgrade to 1.0.1 or later to turn compaction on: that stops further growth but cannot shrink a backend that has already grown, and a cluster that has already raised a NOSPACE alarm needs operator recovery rather than an upgrade.

Access

  • publicAccess.enabled — Exposes Keycloak over HTTPS at the automatically assigned canonical *.cpln.app endpoint. It is deliberately on by default: Keycloak is the identity provider your applications and their users authenticate against, so browsers must reach its login and OIDC endpoints for SSO to work at all, and the admin login is now a credential you created rather than a published default. Disable it only for pure service-to-service deployments; internal access keeps working. A firewall change takes roughly 30 seconds to a few minutes to propagate, so re-test rather than trusting the first response.
  • internalAccess.type — Controls which workloads can reach Keycloak inside Control Plane (none, same-gvc, same-org, or workload-list). With workload-list, list the allowed workloads in internalAccess.workloads.

Backup

The postgresHA.backup and postgres.backup sections are pass-throughs to the backup feature of the corresponding backing store template. Set backup.enabled: true and fill in the provider section (aws, gcp, or minio) to schedule database backups to object storage. For provider setup, backup modes, and restore procedures, see the backing store’s documentation:

Connecting

On a first install of the default HA stack, the Keycloak container waits for the PostgreSQL cluster to come up (logging Waiting for PostgreSQL...) before starting. A default install measured 303 seconds from install to a ready workload, most of that spent waiting on the Patroni and etcd replicas; the dev-mode store (postgres with replicas: 1) is ready in about 2 minutes.

Important Notes

  • Create the admin secret before installing — a missing prerequisite secret leaves the workload waiting on something that does not exist, with zero log lines. See Prerequisites for how to diagnose it.
  • Change the database password before installing (postgresHA.postgres.password / postgres.credentials.password) — it is bundled plumbing, used exactly as given, and it remains a value by design.
If you run more than one release of this template in the same organization, give each its own postgres.config.credentialsSecretName. Secret names are organization-wide, so a second release left on the default name is refused at install and creates nothing — the first release is unaffected.
  • The bootstrap admin is temporary by design — log in, create a permanent admin, then remove it. Its credentials are seeded on first boot only; change the password in the admin console, not by editing the secret.
  • Keep publicAccess enabled for browser SSO — end-user browsers must reach Keycloak’s login endpoints; disable it only for pure service-to-service deployments.
  • Do not disable the HA proxy (postgresHA.proxy.enabled) — Keycloak connects through the HAProxy leader endpoint for writes; the chart enforces this at render.
  • Scaling is operator-driven — change replicas via a template upgrade; there is deliberately no autoscaling, so cluster membership only changes intentionally.
  • Database volumes survive reinstalls — uninstalling and reinstalling under the same release name reuses the persisted data unless the volume sets are deleted.

External References

Keycloak Documentation

Official Keycloak documentation

Server Configuration Reference

All Keycloak server configuration options

Caching and Clustering

How Keycloak’s Infinispan caching and clustering work

Cloud Accounts

Create a Control Plane Cloud Account for backup storage access

Keycloak Template

View the source files, default values, and chart definition