Docs/Operations/Backup & Restore

Backup & Restore

What to back up in a self-hosted install, how to do it with Docker Compose, and what to use on Kubernetes. Nothing is backed up automatically: schedule it yourself and prove it with a restore drill.

Back up the secrets with the data
Back up deploy/compose/.env (or your Kubernetes Secrets) together with the database. APP_ENCRYPTION_KEY decrypts every stored provider key and channel secret; a database without it is not restorable in any useful sense.

What to back up

DataWhere it livesNeeded?
Platform database (all tenant_* schemas and the control plane)postgres service, postgres-data volumeYes — irreplaceable
Keycloak (realm, users, credentials, clients)Full: keycloak-db; Lite: keycloak-data volumeYes
Files (uploads, generated artifacts)Full: seaweedfs-data volume or your S3 bucket; Lite: core-storage volumeYes
Secretsdeploy/compose/.envYes
Valkey, Temporal history, Langfuse, Prometheus/Lokitheir own volumesOptional — rebuildable or disposable

Compose: back up

C="scripts/vegaduta compose"
$C exec -T postgres pg_dumpall -U agentic | gzip > vegaduta-db-$(date +%F).sql.gz
$C exec -T keycloak-db pg_dump -U keycloak keycloak | gzip > vegaduta-keycloak-$(date +%F).sql.gz   # Full tier
# Lite: Keycloak lives in the keycloak-data volume — stop keycloak and archive it:
docker run --rm -v vegaduta-lite_keycloak-data:/d -v "$PWD":/b alpine tar czf /b/keycloak-data.tgz -C /d .
cp deploy/compose/.env vegaduta-env-$(date +%F).bak

Also archive the core-storage (Lite) or seaweedfs-data (Full) volume, or back up your external S3 bucket. Copy backups off the host; a disk failure otherwise takes the database and its backups together.

Compose: restore

  1. On a fresh host, check out the same release and put the backed-up deploy/compose/.env in place (same APP_ENCRYPTION_KEY).
  2. Start only the databases: scripts/vegaduta compose up -d postgres keycloak-db.
  3. Restore: gunzip -c vegaduta-db-<date>.sql.gz | scripts/vegaduta compose exec -T postgres psql -U agentic -d postgres, and the Keycloak dump into keycloak-db (or the keycloak-data archive for Lite).
  4. Restore the file volume or bucket, then scripts/vegaduta up with the same flags as before.
Restore into the right Postgres image
Restoring into a stock postgres:16 image silently loses every pgvector column. Restore into the release postgres image (deploy/postgres: PostgreSQL 16 with pgvector and Apache AGE), which is what the postgres service already runs.

Restore drill

Run one after setting up backups and after every major upgrade: restore the latest dump into a throwaway container of the release postgres image and check that at least one tenant_% schema exists and the control-plane tables are queryable. Windows hosts can use the helper scripts in scripts/backup/ (pg-backup.ps1 with rotation, register-backup-task.ps1 for a nightly scheduled task, verify-restore.ps1 for the drill); read their headers first.

Kubernetes

Upgrades and rollbacks

scripts/vegaduta upgrade backs up .env but not the database. Take a database backup before every upgrade: Flyway migrations are forward-only, so a restore is the only way to undo one. See Rollback & Recovery.

Evidence & references