Restore after a live cluster
Standing up a new node is not this page. Use Provision from scratch for k3s, Helm, Argo, Infisical GUI, and Keycloak first-login. That playbook is the same on every server.
This page is after a cluster existed: Git still rebuilds objects; data and out-of-band credentials do not come back from a push. Example app names (Penvoice, Talon) are illustrations.
What’s in Git vs by hand
Section titled “What’s in Git vs by hand”| In Git (Argo CD) | By hand |
|---|---|
| Operators, Infisical server CRs, ApplicationSet overlays | k3s + Helm — Provision |
Rollout, Ingress, Redis, CNPG Cluster shape | Out-of-band Secrets — Reference |
Keycloak CR + realm YAML (keycloak-config-cli) | keycloak-config-cli-sa per Keycloak namespace (first time: Provision §8) |
Infisical operator CRs (projectId, env slug) | Infisical values (re-type in the GUI if the Infisical DB was empty) |
Postgres data is restored from Oracle Object Storage — Backup & restore. Do not restore a CNPG cluster in place.
After a wipe or empty node
Section titled “After a wipe or empty node”Follow Provision end to end. Do not apply bootstrap/root-app.yaml from a main that still
has the old single-namespace layout. Then restore each Postgres from object storage if you need the old data.
Locked out of Keycloak (no data loss)
Section titled “Locked out of Keycloak (no data loss)”Use this when keycloak-config-cli cannot authenticate or you cannot open the admin console. It does not wipe realm
data. Repeat per env (keycloak-staging or keycloak-prod). Substitute that namespace below.
If a permanent admin from Provision §8 still works, stop here.
bootstrapAdmin is a no-op once a master realm exists. Recreating a temp-admin Secret and restarting does nothing.
Use the bootstrap-admin CLI against the DB. Every kubectl below is on the node or locally —
Access & consoles → kubectl.
-
Stop Keycloak (CLI needs exclusive DB access):
Terminal window kubectl -n keycloak-<env> patch keycloak keycloak --type merge -p '{"spec":{"instances":0}}' -
Store a recovery password (never print it):
Terminal window kubectl -n keycloak-<env> create secret generic keycloak-recovery-admin-creds \--from-literal=password="$(openssl rand -base64 24)" -
One-off Pod — same image and DB as the instance, command
bootstrap-admin:apiVersion: v1kind: Podmetadata: { name: keycloak-recovery-admin, namespace: keycloak-<env> }spec:restartPolicy: Nevercontainers:- name: kc-bootstrapimage: quay.io/keycloak/keycloak:26.6.3 # match the live instancecommand: [/opt/keycloak/bin/kc.sh, bootstrap-admin, user, --username, recovery-admin, --password:env, RECOVERY_PASSWORD]env:- { name: KC_DB, value: postgres }- { name: KC_DB_URL_DATABASE, value: keycloak }- { name: KC_DB_URL_HOST, value: keycloak-pg-rw }- name: KC_DB_USERNAMEvalueFrom: { secretKeyRef: { name: keycloak-pg-app, key: username } }- name: KC_DB_PASSWORDvalueFrom: { secretKeyRef: { name: keycloak-pg-app, key: password } }- name: RECOVERY_PASSWORDvalueFrom: { secretKeyRef: { name: keycloak-recovery-admin-creds, key: password } }Terminal window kubectl apply -f recovery-pod.yamlkubectl -n keycloak-<env> logs keycloak-recovery-admin | grep "Created temporary admin"kubectl -n keycloak-<env> delete pod keycloak-recovery-admin -
Bring Keycloak back:
Terminal window kubectl -n keycloak-<env> patch keycloak keycloak --type merge -p '{"spec":{"instances":1}}' -
Log in as
recovery-admin(also ~2h). Immediately recreate your permanent admin and, if needed,keycloak-config-cli— same GUI steps as Provision §8. Deletekeycloak-recovery-admin-credswhen done.
Wiping one Keycloak (deliberate empty realm)
Section titled “Wiping one Keycloak (deliberate empty realm)”Only when you want to lose that env’s realm data and re-apply
workloads/keycloak/overlays/<env>/realms/ from nothing.
On the node or locally.
-
Stop Keycloak:
Terminal window kubectl -n keycloak-<env> patch keycloak keycloak --type merge -p '{"spec":{"instances":0}}' -
Delete the CNPG cluster:
Terminal window kubectl -n keycloak-<env> delete cluster keycloak-pg -
Check for leftover PVCs, then delete any that remain:
Terminal window kubectl -n keycloak-<env> get pvckubectl -n keycloak-<env> delete pvc -l cnpg.io/cluster=keycloak-pg -
Delete leftover Secrets — the label below usually covers it, or delete the specific initial-admin name you see:
Terminal window kubectl -n keycloak-<env> delete secret -l app=keycloak -
Bring Keycloak back up:
Terminal window kubectl -n keycloak-<env> patch keycloak keycloak --type merge -p '{"spec":{"instances":1}}'
Argo recreates an empty Cluster. bootstrapAdmin fires. Redo Provision §8, then let the Sync Job apply realms. Copy new
confidential client secrets into the Infisical GUI for the apps that use them.