Backup and restore
Everything the operator knows lives in PostgreSQL and in cluster resources. Back those up and an installation can be rebuilt; there is no hidden state anywhere else.
What to back up
| What | Where | If you lose it |
|---|---|---|
| The database | The bundled PostgreSQL's volume, or the external database you pointed externalDsnExistingSecret at | Findings, decisions, exceptions, audit log, evidence archive, users and the licence certificate are gone. This is the backup that matters. |
| Policies | ImageSecurityPolicy resources — in the cluster, and ideally in git already | Re-apply from your repository; the chart reseeds a default if none exists. |
| The session key | Secret attestkeep-session (unless you supplied api.session.existingSecret) | Everyone is signed out and signs in again. Nothing else. |
| The data key | Secret attestkeep-data-key — generated by the chart on install, unless you supplied api.dataKey.existingSecret | The issue-tracker credentials sealed under it cannot be opened. Each tracker channel has to have its token entered again, which re-seals it under the new key; nothing else in the product depends on it. |
| The evidence signing key | Secret attestkeep-evidence-key — created by the operator, not the chart | A new key is generated and new records seal under it, but checkpoints and evidence documents signed by the old key no longer verify against the installation's current key. History survives; the ability to vouch for old signatures does not. See the evidence trust model. |
The webhook's serving certificate is not on the list: the operator reissues it and republishes the CA bundle on its own. The activation key is not either — reinstalling into the same cluster produces the same fingerprint, so the existing licence slot is simply picked up again at activation, as Licensing describes.
Configuration export — the bundle
Since 0.3.4, Settings → Backup exports a JSON bundle of the configuration you built by hand: notification channels, triage decisions, the user list and policies. It exists for the two moves a database dump is the wrong shape for — standing up a second cluster with the same setup, and keeping a portable copy of decisions that took meetings to make.
- Credentials never leave. A webhook URL is the credential for the channel it names, so it is stripped on export; such a channel imports disabled and the report tells you to enter the URL again. A tracker channel's token is stripped the same way, ciphertext included — the sealed value is bound to this installation's data key and would not open in the one the bundle is for — so an imported GitHub, GitLab or Jira channel arrives disabled until its token is entered. Email recipient addresses stay — they are addresses, not secrets. Password hashes are never in the bundle.
- Import previews before it writes. The same bundle is first evaluated as a dry run: you see what would be added and what would be skipped, and confirm before anything changes.
- Existing records always win. A conflicting incoming channel, triage decision or policy is skipped and named in the report — never merged over what is there.
- Users are reported, not created. An account without a password or an invitation would be a door nobody can open honestly; the report lists who existed on the exporting side so you can invite them properly.
- Both directions land in the audit log, with counts.
Backup history. From 1.3.1 the same page lists every export and import, ten to a page: when, by whom, and what the bundle carried — for an import, what was added, how many records were already there, and the cluster and time the bundle was exported from. A preview is not listed. The operator does not keep the bundle itself; the file you downloaded is the only copy.
The bundle complements the database dump; it does not replace it. Findings, admission history, the ledger and its checkpoints only exist in PostgreSQL.
Backing up the bundled PostgreSQL
Attestkeep does not take database backups: the dump is yours to run, schedule and keep. If you brought your own database, your existing backup regime already covers it and this section is not for you. The bundled database is a single-replica StatefulSet named attestkeep-postgresql, and a plain SQL dump is the portable answer:
kubectl -n attestkeep exec statefulset/attestkeep-postgresql -- \
sh -c 'pg_dump -U "$POSTGRES_USER" "$POSTGRES_DB"' > attestkeep.sql
Schedule it with whatever already runs your cron jobs, and store the file with your other backups. A volume snapshot of the PVC works too, if your storage class offers one — the dump is simply the answer that restores anywhere, including into a different storage class or a different cluster.
Restoring
Install the chart, stop the operator so nothing writes or migrates mid-restore, load the dump, start it again:
kubectl -n attestkeep scale deploy/attestkeep deploy/attestkeep-scanner --replicas=0
kubectl -n attestkeep exec -i statefulset/attestkeep-postgresql -- \
sh -c 'psql -U "$POSTGRES_USER" -d postgres -c \
"DROP DATABASE \"$POSTGRES_DB\" WITH (FORCE); CREATE DATABASE \"$POSTGRES_DB\" OWNER \"$POSTGRES_USER\""'
kubectl -n attestkeep exec -i statefulset/attestkeep-postgresql -- \
sh -c 'psql -q -U "$POSTGRES_USER" "$POSTGRES_DB"' < attestkeep.sql
kubectl -n attestkeep scale deploy/attestkeep --replicas=2
kubectl -n attestkeep scale deploy/attestkeep-scanner --replicas=1
Restoring a dump into the same or a newer operator version is supported: migrations are recorded in the dump, and a newer operator applies only what the dump does not already carry. Restoring a newer dump into an older operator is not — migrations move forward only, which is the same rule Upgrade states for rollbacks.
What a restore means for your evidence
Everything recorded after the dump was taken is gone, and the evidence package does not pretend otherwise. The operator stamps a heartbeat as it runs; on the first pass after a restore it finds the last stamp at dump age and records the whole span since as a window in which the control was not operating. A period report covering it shows the gap, exactly as it shows any other outage.
That is the honest cost of restoring from backup: you get your history back up to the dump, and the document says plainly where history is missing. A restore that could silently paper over the lost window would be a way to rewrite the record, and this product's evidence would be worth less for having it.