Overview
Keycloak is an open-source identity and access management platform that provides single sign-on, OIDC and SAML identity federation, user federation (LDAP and Active Directory), social login, and fine-grained authorization. This template runs Keycloak 26 in production mode, clustered across two replicas by default, with a highly available PostgreSQL backing store so that restarts and upgrades do not interrupt sign-ins. A lighter single-instance PostgreSQL store is available for dev/test. All durable state — realms, users, and active sessions — lives in PostgreSQL. The Keycloak tier itself keeps nothing on disk, so it has no volume set of its own.cpln workload exec, cpln logs and uninstalling all work against that GVC.What Gets Created
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. The template creates no admin secret of its own; it references yours by name and grants the workloadreveal on exactly that one secret.
Create the admin credentials secret
username and password. Secrets are org-level, so no GVC flag is involved:admin.secretName to this name.Read the password back when you need it
-o yaml is required; without it the command prints only a summary table:postgres.credentials.*, so there is nothing to create — only a placeholder to change at install time. Optional database backups need a bucket plus a cloud account (AWS or GCP) or a MinIO credentials secret; see Backing Up.
Installation
Install from the marketplace registry, naming your admin secret and replacing the placeholder database password:UI
CLI
Terraform
Pulumi
Configuration
Keycloak
replicas—2or more runs Keycloak as a cluster: the replicas discover each other through the shared database, so a single replica restarting does not interrupt sign-ins.1runs with clustering disabled, for dev/test. Clustered replicas talk to each other on ports7800and57800, soreplicasabove1needs aninternalAccess.typeother thannone— the chart refuses the combination at render.resources— Per-replica CPU and memory. The JVM heap is sized to 70% ofmaxMemory; keep it at1.5Gior above. The block exposes both a reservation (minCpu,minMemory) and a limit (maxCpu,maxMemory).
Admin Bootstrap
admin.secretName— The dictionary secret you created in Prerequisites. Keycloak reads it on first boot only, to create a temporary bootstrap admin when no admin account exists yet. Editing the secret on a running install changes nothing; change the password in the admin console instead, and remove the temporary account once you have created a permanent one (see First Run).
Database Credentials
postgres.credentials.*— Username, password and database name for the bundled database. They feed whichever store is enabled, including the default HA store, even though the rest of thepostgresblock is off by default. The template writes them into the dictionary secret named bypostgresHA.config.credentialsSecretNameorpostgres.config.credentialsSecretName, and both Keycloak and the database read that secret. Change the password before installing.
Backing Store
Exactly one of the two stores must be enabled; the chart refuses both-on and both-off at render. Highly available PostgreSQL (default). Three Patroni-managed PostgreSQL replicas, three etcd replicas and an HAProxy endpoint that routes Keycloak’s connections to the current leader, from the PostgreSQL Highly Available template:postgresHA.config.credentialsSecretName/postgres.config.credentialsSecretName— Name of the database credentials secret this template creates. Secret names are organization-wide: a second release left on the default name is refused at install (see Troubleshooting).postgresHA.proxy.enabledmust staytrue— Keycloak writes through the HAProxy leader endpoint, and the chart refuses the install at render if it is disabled.- Any other setting of the backing template can be set under the same prefix (
postgresHA.pgbouncer.*,postgresHA.etcd.*,postgres.pgbouncer.*, volume-set autoscaling, and so on); see the backing template’s page for those keys.
Access
publicAccess.enabled— Exposes Keycloak over HTTPS at the automatically assigned canonical*.cpln.appendpoint. It is on by default because Keycloak is the identity provider your applications’ users sign in to: browsers must reach its login and OIDC endpoints for SSO to work at all. Disable it only for pure service-to-service deployments; internal access keeps working. An access change can take a couple of minutes to take effect, so re-test rather than trusting the first response.internalAccess.type— Which workloads can reach Keycloak inside Control Plane (none,same-gvc,same-org, orworkload-list). Withworkload-list, list the allowed workloads ininternalAccess.workloads.
Connecting
First Run
Open the admin console
https://CANONICAL_ENDPOINT/admin. With publicAccess.enabled: false, forward the port as above and use http://localhost:8080/admin instead.Sign in with the bootstrap admin
username and password from your admin secret (cpln secret reveal ADMIN_SECRET_NAME -o yaml).Create a permanent admin and remove the temporary one
master realm, create a permanent admin user with the admin role, sign in as that user, and delete the bootstrap account. Keycloak shows a warning in the console until the temporary account is gone.Create a realm for your applications
master realm for administration and register your applications as clients in a realm of their own. Their OIDC discovery URL is the one in the table above, with REALM_NAME replaced.Operations
Backing Up
Backups are a pass-through to the backing store’s backup feature: everything underpostgresHA.backup is handed to the PostgreSQL Highly Available template, and everything under postgres.backup to the PostgreSQL template. Set enabled: true and fill in the section for your provider.
aws and gcp are set up exactly as for the backing template — follow the PostgreSQL Highly Available backup prerequisites for the default store or the PostgreSQL backup prerequisites for the single-instance store, and use the key names shown above (prefixed with postgresHA. or postgres.). Backup modes and schedules are described under PostgreSQL Highly Available — Backup and PostgreSQL — Backup.
MinIO is the one provider with a prerequisite secret. Before enabling provider: minio, create a dictionary secret holding exactly the keys accessKey and secretKey, and set postgresHA.backup.minio.credentialsSecretName (or postgres.backup.minio.credentialsSecretName) to its name. For the MinIO template these are its admin.username and admin.password:
status.versions[].message described in Prerequisites.
Restoring a Backup
Keycloak keeps no state outside PostgreSQL, so restoring Keycloak means restoring its database. Follow the backing store’s restore procedure — PostgreSQL Highly Available — Restoring a Backup for the default store, PostgreSQL — Restoring a Backup for the single-instance store — against the database host and credentials listed under Connecting. Then restart Keycloak so every replica reloads from the restored database rather than from its in-memory caches:Upgrading From 1.0.x
Version1.1.0 moved the bootstrap admin login out of Helm values and into the prerequisite dictionary secret described in Prerequisites. Earlier versions shipped a username and a working default password as values.
keycloak: admin.password was REMOVED in 1.1.0. Put it in a dictionary secret (key: password) together with username, and set admin.secretName to that secret's name. Leaving admin.secretName empty is refused the same way. There is no compatibility fallback.
1.0.x default password (change-me-keycloak-admin), treat it as compromised and change it in the console now.1.0.0 with the default HA store also predate the etcd history compaction that the bundled PostgreSQL Highly Available template now turns on. Upgrading stops further growth of the etcd backend but cannot shrink one that has already grown; see that template’s page for the symptoms and recovery.
Upgrading From 1.1.0
Version1.2.0 adopted the postgres 3.4.1 template for the single-instance store, which no longer takes credentials as values. This template absorbed that change rather than passing it on — there is no new prerequisite, only renames on the single-instance path:
postgres.credentials.*. Move the keys and the upgrade proceeds. The HA path was unchanged in 1.2.0.
Upgrading From 1.2.x and 1.3.0
Version1.3.0 adopted the postgres-highly-available 2.5.0 template for the default store, which likewise no longer takes credentials as values. The HA store now reads the same template-created credentials secret as the single-instance store, named by the new postgresHA.config.credentialsSecretName key:
postgres.credentials.username, password and database to the same values your install already uses under postgresHA.postgres.*: the database volume was initialised with those credentials and keeps them. Changing the database password as part of this upgrade has not been verified and is not recommended.
Upgrading From 1.3.1
Version1.4.0 renamed the Keycloak resource limits so it is unambiguous which number is the ceiling. Rename the two keys in your values; nothing else changed.
resources.cpu or resources.memory is refused at render: keycloak: resources.cpu was RENAMED to resources.maxCpu. The reservation keys minCpu and minMemory are unchanged.
Scaling and Availability
- Keycloak replicas. Change
replicasand upgrade the release; there is deliberately no autoscaling, so cluster membership only changes when you change it. Clustered replicas (2or more) share realm, user and session state through the database, so one replica restarting does not interrupt sign-ins. Withreplicas: 1a restart is a short outage. - Rolling upgrades are not guaranteed to restart one replica at a time. Realms, users and sessions live in PostgreSQL and survive regardless, but plan for a brief gap in availability during a template upgrade rather than assuming a strictly serialized rollout.
- The first
helm upgradeafter an install can restart the bundled database even when none of its values changed; Keycloak waits for it and resumes. - Database tier. The default store runs three Patroni replicas with automatic leader failover; Keycloak always connects through the HAProxy leader endpoint, which is why
postgresHA.proxy.enabledmust staytrue. AdjustpostgresHA.replicasandpostgresHA.volumeset.capacityfor size; the single-instance store (postgres.enabled: true) trades failover for a smaller footprint. - Uninstalling deletes the database volume sets. The database volume set (and, in HA mode, etcd’s) is deleted with the release, so data does not survive a reinstall — enable backups.
Troubleshooting
The Keycloak workload never starts and cpln logs returns nothing
The Keycloak workload never starts and cpln logs returns nothing
admin.secretName (or, with MinIO backups, the secret named by backup.minio.credentialsSecretName) does not exist. The container never ran, so there is nothing to log.Fix: read the message that names the missing secret, create it, then force a redeployment to skip the wait:The install or upgrade is refused at render
The install or upgrade is refused at render
Logs show Waiting for PostgreSQL for several minutes
Logs show Waiting for PostgreSQL for several minutes
A second release is refused: cannot be updated because it is being managed by a different release
A second release is refused: cannot be updated because it is being managed by a different release
my-keycloak-db-credentials by default) and secret names are organization-wide, so a second Keycloak release on the same name tries to take over a secret the first release owns. Nothing is shared, overwritten or deleted; the second release simply does not install.Fix: give each release its own postgresHA.config.credentialsSecretName (and postgres.config.credentialsSecretName) and install again.I changed the admin secret but the old password still works
I changed the admin secret but the old password still works
The admin console is unreachable with publicAccess disabled
The admin console is unreachable with publicAccess disabled
publicAccess.enabled: false there is no canonical endpoint to browse to; only workloads inside Control Plane can reach Keycloak.Fix: forward the HTTP port and open http://localhost:8080/admin:Important Notes
- Create the admin secret before installing — a missing prerequisite secret wedges the deployment with zero log lines;
status.versions[].messageis the only diagnostic (see Prerequisites). - Change the database password before installing (
postgres.credentials.password) — it is used exactly as given and feeds whichever store is enabled. - Give each release its own
credentialsSecretName(postgresHA.config.andpostgres.config.) — secret names are organization-wide, and a second release on the default name is refused at install. - The bootstrap admin is temporary by design — sign in, create a permanent admin, then delete the bootstrap account. Its credentials are read on first boot only, so change the password in the console, not by editing the secret.
- Keep
publicAccessenabled 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 writes through the HAProxy leader endpoint; the chart refuses the install otherwise. replicasabove1needs internal access — setinternalAccess.typeto anything butnone, or the install is refused.- Scaling is operator-driven — change
replicasvia a template upgrade; there is deliberately no autoscaling. - Uninstalling deletes the database volume sets — the database (and, in HA mode, etcd) volume sets go with the release, so data does not survive a reinstall. Enable backups.