Skip to main content

Backup and restore

Back up PostgreSQL, artifact storage, and secret configuration together. Record the installed release and test restoration on an isolated host before relying on the backup.

What has to be backed up​

DeploymentBackup set
ApplianceComplete data disk, installed version, and VM configuration. Keep the matching OS image available.
ComposePostgreSQL dump, testvibe_blobdata volume, .env, and version-pinned Compose file.
KubernetesPostgreSQL, artifact PVC, protected Helm values and Secrets, and chart/image versions.

New Compose and Kubernetes installations store the secret-protection key in PostgreSQL. If an existing deployment explicitly sets TESTVIBE_SECRET_PROTECTION_KEY, preserve that exact value too. The appliance keeps its generated configuration on the data disk. Losing the key makes encrypted secrets unreadable; creating a new key does not recover them.

Store backups securely. Exported Kubernetes Secret YAML contains credentials encoded in base64, not encrypted.

Taking the backup​

Pause new work and let active tests, generations, and uploads finish. Keep application writers stopped until both database and artifact backups are complete. A database dump is consistent by itself, but that does not synchronize it with a separate artifact copy.

Appliance​

Shut down the VM cleanly through your hypervisor and copy or snapshot the complete data disk. Record the OS release and VM settings. Copying a running virtual disk without application-consistent backup coordination is not a substitute. The restricted recovery console has no general-purpose shell; use hypervisor tooling or support-assisted maintenance.

Docker Compose​

Run from the installation directory. These commands assume standard volume and service names in the released bundle and a POSIX shell. Use a new backup directory for each backup set.

mkdir -p backup
docker compose stop web runner browser blobserver
docker compose exec -T postgres \
pg_dump -U tvadmin -Fc testvibe > backup/testvibe-db.dump
docker run --rm \
-v testvibe_blobdata:/data:ro \
-v "$PWD/backup":/backup \
alpine tar -czf /backup/testvibe-blob.tar.gz -C /data .
cp .env docker-compose.yml backup/

Check each command succeeded, the files are nonempty, and PostgreSQL 16 pg_restore --list can read the dump. Then resume services:

docker compose start blobserver runner browser web
docker compose ps

Do not tar a live PostgreSQL data directory. Use a database dump, PostgreSQL-aware backup tooling, or stop the database before a full volume backup.

Kubernetes​

Record replica counts, drain work, and scale web, runner, browser, and artifact deployments down. Coordinate with GitOps reconcilers and autoscalers so they do not restart writers during the backup. Use your provider's backup tooling for an external database. For the bundled database:

kubectl -n testvibe exec statefulset/testvibe-postgresql -- \
pg_dump -U tvadmin -Fc testvibe > testvibe-db.dump
helm get values testvibe -n testvibe -o yaml > installation-values.yaml
kubectl -n testvibe get secret testvibe-secrets -o yaml > testvibe-secrets.yaml

Snapshot or copy the artifact PVC while writers remain stopped. Wait for snapshot completion before restoring the recorded replica counts. If you use secrets.existingSecret, export that Secret instead. Protect the exported files.

How to restore​

Restore database, artifacts, and credentials from the same backup set. Start with the same application release that created it; upgrade separately after verifying the restore. Never start older code against a newer migrated database.

Appliance​

Create an isolated VM using the matching OS disk and restored data disk. Do not attach the new image's empty data disk alongside it. Boot, wait for readiness, and verify installation identity, license, users, and existing artifacts. Keep the original VM shut down during a production replacement.

Docker Compose​

Use a separate recovery host with empty standard volumes. Preserve the source volumes until the restore is verified. Restore the backed-up .env and matching Compose file before starting services.

docker volume create testvibe_blobdata
docker run --rm \
-v testvibe_blobdata:/data \
-v "$PWD/backup":/backup:ro \
alpine tar -xzf /backup/testvibe-blob.tar.gz -C /data
docker compose up -d postgres
docker compose exec postgres pg_isready -U tvadmin -d testvibe

Wait until PostgreSQL accepts connections, then restore into the empty database:

docker compose exec -T postgres \
pg_restore -U tvadmin -d testvibe --exit-on-error < backup/testvibe-db.dump
docker compose run --rm migrate

Stop if restoration or migrations fail. When successful:

docker compose up -d
docker compose ps

Kubernetes​

Restore into an isolated namespace or cluster using your storage and database recovery tooling. Restore protected values and Secrets before starting consumers. Database and artifact storage must contain the recovered data before enabling the application.

The chart always creates a migration Job: do not install or upgrade it while a database restore is in progress. For an existing isolated recovery installation, stop all writers and ensure no migration Job is running before loading the database. For a new cluster, restore database and storage resources first, using the names and settings in the matching chart, or configure the chart to use your restored external database.

After restoration completes, apply the matching version with the complete protected values file:

helm upgrade --install testvibe oci://testvibe.azurecr.io/charts/testvibe \
--version <restored-version> -n testvibe -f installation-values.yaml
kubectl -n testvibe get jobs
kubectl -n testvibe rollout status deploy/testvibe-web

Verify the new migration Job completed successfully. Keep the schema-checking init container enabled. There is no separate Admin deployment to restore or enable.

Verify before returning to service​

Sign in, open a project from before the backup, load an existing trace and screenshot, and run a small test. Confirm installation identity and license under Settings → Administration → License. Check public URLs, email, and identity callbacks before switching traffic.