Backup & disaster recovery¶
One database holds your durable state — back it up well and recovery is straightforward.
What it is¶
HelixIAM's persistent state lives in a single PostgreSQL database: realms, users, clients, keys, policy and audit history. helix-iam-server itself holds nothing that needs backing up beyond that database — protecting your deployment comes down to protecting that one database (plus, in one case below, your keystore, and Redis if you rely on session continuity across a Redis restart).
Back up and restore the database¶
HelixIAM ships no backup scripts of its own (the Helm chart has an example pg_dump CronJob in examples/): use PostgreSQL's own tools, or your managed database's snapshots and point-in-time recovery. A logical backup in PostgreSQL's custom format:
# Backup (custom format, compressed)
pg_dump --host "$DB_HOST" --username "$DB_USERNAME" --dbname helixiam --format=custom --file helixiam.dump
# Restore into an empty database
createdb --host "$DB_HOST" --username "$DB_USERNAME" helixiam_restore
pg_restore --host "$DB_HOST" --username "$DB_USERNAME" --dbname helixiam_restore --no-owner helixiam.dump
On the Docker Compose stack the same tools run inside the postgres container:
Schedule it with whatever runs your other database jobs (a Kubernetes CronJob, your cloud's managed backups), and test restores.
DB_ENCRYPTION is part of your backup
Sensitive columns are encrypted with DB_ENCRYPTION. A database backup is useless without the exact same key, and the key must never change after first boot. Store DB_ENCRYPTION securely and separately from the database dump, back it up, and never rotate it. See security hardening.
Back up /jks if you seed keys from files
If you seed the master-realm signing key from files, include the /jks keystore in your backup. Without it, a restored database will not match the published JWKS and tokens will fail to verify. See Realm keys.
Realm export — portable config backup¶
The pg_dump above is your authoritative, byte-for-byte backup. Alongside it, Helix can export a single realm as a self-contained JSON document — realm settings, clients, roles, users, flows, identity providers and more. It is the right tool for migrating a realm between environments, snapshotting config into version control, or seeding a fresh install; it complements (does not replace) the database backup. The examples below assume you have set $HELIX_URL / $REALM and logged in — see Authenticating to the API.
Export a realm — GET /admin/realms/{realm}/export¶
curl -s -b cookies.txt "$HELIX_URL/admin/realms/$REALM/export" > $REALM-export.json
jq 'keys' $REALM-export.json
[
"accountConsole", "adminRoles", "agents", "applications",
"authorizationServices", "clientProtocolMappers", "clientRoles",
"clientScopes", "clients", "flows", "formatVersion", "groups",
"identityProviders", "messageTemplates", "messagingProviders",
"organizations", "realm", "resourceIndicators", "roles", "samlClients",
"scimTargets", "serviceAccountRoles", "users", "webhooks", "workloadIdentity"
]
The document carries a formatVersion and a requiredEnv list naming the secrets the target environment must supply (identity-provider, webhook, SCIM-target, messaging and CAPTCHA secrets, as HELIX_<REALM>_… variables) — the export never contains those secret values. requiredEnv is null when the realm has none; for a realm gov with a webhook named audit:
Re-import — POST /admin/realms/{realm}/import¶
Restore or seed a realm by POSTing the exported document back (a write, so refresh the CSRF token first):
curl -s -b cookies.txt -c cookies.txt "$HELIX_URL/admin/realms/$REALM/export" >/dev/null
CSRF=$(awk '($6=="__Host-XSRF-TOKEN"||$6=="XSRF-TOKEN")&&$7~/^r1\./{t=$7} END{print t}' cookies.txt)
curl -s -b cookies.txt \
-H "Content-Type: application/json" -H "X-XSRF-TOKEN: $CSRF" \
--data-binary @"$REALM-export.json" \
"$HELIX_URL/admin/realms/$REALM/import"
Config, not durable state
Realm export is a configuration backup, not a substitute for the database dump: it does not carry event history, encrypted credential material, or live sessions. Use it for migration and config-as-code; use pg_dump for full disaster recovery. A Keycloak realm JSON can be imported via POST /admin/realms/{realm}/import/keycloak.
RPO and RTO¶
- RPO (recovery point objective) equals your backup interval — the most data you can lose. A nightly backup means up to ~24 h of loss. Tighten the RPO toward zero with WAL archiving / point-in-time recovery (PITR).
- RTO (recovery time objective) is how long restore takes: provision PostgreSQL,
pg_restorethe dump, restore/jksif used, and start helix-iam-server and the console. Because the server carries no state outside the database, it returns to service as soon as the database is up.
How to recover¶
- Provision a PostgreSQL instance.
pg_restorethe latest dump into it (see above), or restore your managed snapshot.- Restore the
/jkskeystore if you seed keys from files. - Ensure
DB_ENCRYPTIONmatches the original. - Start helix-iam-server, then the console. With several replicas, restart them all: a replica only reloads identity providers whose version went up, and a restore can lower it.