Backup & restore¶
Axium keeps all its state in PostgreSQL. Neither the core nor the ui write to disk, so a complete backup is the database plus the master key.
A backup without the master key is incomplete
Provider credentials are stored encrypted with MASTER_ENCRYPTION_KEY. A
restored database with a different key starts fine, but every provider
fails to authenticate until its credentials are entered again. Store the
key with the backups, in a separate secret store, with the same retention.
Docker¶
Logical dump with pg_dump, which works across PostgreSQL minor versions and
is easy to inspect:
Restore into an empty database:
docker exec -i axium-db pg_restore -U axium -d axium-api --clean --if-exists < axium-2026-10-19.dump
Stop the core while restoring, then start it again. It detects the installed schema and does not reinstall anything.
Alternatively, snapshot the volume with the database stopped:
docker stop axium-core axium-db
docker run --rm -v axium-pgdata:/data -v "$PWD":/backup alpine \
tar czf /backup/axium-pgdata-$(date +%F).tgz -C /data .
docker start axium-db axium-core
Google Cloud¶
The installer creates the Cloud SQL instance with --no-backup to keep the
pilot cheap. For production enable automated backups and point-in-time
recovery:
gcloud sql instances patch axium-db \
--backup-start-time=03:00 \
--enable-point-in-time-recovery \
--retained-backups-count=14
Take an on-demand backup before an upgrade:
The master key is in the Cloud Run service configuration. Read it back with:
gcloud run services describe axium-core --region europe-west1 \
--format='value(spec.template.spec.containers[0].env)'
and store it in Secret Manager or your password manager.
What to test¶
A backup you have not restored is a hypothesis. Once a quarter, restore the latest dump into a scratch database, start a core against it with the production master key and check that:
GET /v1/install/statusanswersinstalled.- A request through a proxy app reaches the provider, which proves the credentials decrypt.