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.
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
| Data | Where it lives | Needed? |
|---|---|---|
Platform database (all tenant_* schemas and the control plane) | postgres service, postgres-data volume | Yes — irreplaceable |
| Keycloak (realm, users, credentials, clients) | Full: keycloak-db; Lite: keycloak-data volume | Yes |
| Files (uploads, generated artifacts) | Full: seaweedfs-data volume or your S3 bucket; Lite: core-storage volume | Yes |
| Secrets | deploy/compose/.env | Yes |
| Valkey, Temporal history, Langfuse, Prometheus/Loki | their own volumes | Optional — 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
- On a fresh host, check out the same release and put the backed-up
deploy/compose/.envin place (sameAPP_ENCRYPTION_KEY). - Start only the databases:
scripts/vegaduta compose up -d postgres keycloak-db. - Restore:
gunzip -c vegaduta-db-<date>.sql.gz | scripts/vegaduta compose exec -T postgres psql -U agentic -d postgres, and the Keycloak dump intokeycloak-db(or thekeycloak-dataarchive for Lite). - Restore the file volume or bucket, then
scripts/vegaduta upwith the same flags as before.
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
- Bundled PostgreSQL is a CloudNativePG
Cluster: configure its backup (object storage, scheduled backups) per the CNPG documentation. With external PostgreSQL, use your provider's backups and point-in-time recovery. - Back up the Secret named by
global.core.appSecret.existingSecret(or the generated<release>-core-app) with the database. - Bundled Keycloak and SeaweedFS keep data on their PVCs; back those up with your volume snapshot tooling, or use external services.
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
deploy/README.md(Backup, Upgrade, Lite → full),deploy/helm/README.md.deploy/compose/docker-compose.yml,lite.yml(volumes);scripts/backup/.