Skip to content

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:

docker exec axium-db pg_dump -U axium -Fc axium-api > axium-$(date +%F).dump

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:

gcloud sql backups create --instance=axium-db

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/status answers installed.
  • A request through a proxy app reaches the provider, which proves the credentials decrypt.