.env, config overlay, .key.yaml files and compose.override.yaml together in protected storage. If uploads use an external bucket, back up that bucket separately.
Make and check a backup
Run the script while thepg service is running, and copy its output off the host:
tar tzf backups/mirobody-uploads-YYYYMMDD-HHMMSS.tar.gz after replacing the filename. An external bucket needs its own restore drill.
For a full rehearsal, use a protected, isolated test host: clone the code version recorded with the backup, configure it as a fresh server deployment without public access, and copy over the backup plus its matching keys and configuration. Start its empty stack, then run Recover a deployment on that test host, including the upload archive or external bucket restore. Sign in, open a representative restored record and an uploaded file, and check the health response. Keep production’s volumes and network out of this test. The scratch-database check above is a faster archive check; it does not replace this full rehearsal.
Recover a deployment
Stop application writes but leave Postgres running. Replace the example dump name with the backup you selected:holistic_db_restored already exists. Set PG_DBNAME=holistic_db_restored in .env so both Compose and the application select the restored database. Restore the matching encryption keys and configuration before starting the app; encrypted records are unreadable under newly generated keys.
If files were stored locally, find the actual upload volume name with docker volume ls. A checkout named mirobody normally has mirobody_mirobody_upload. Confirm the named volume already exists before restoring; otherwise docker run -v would silently create an empty one. Restore the matching archive into that volume:
.env, and encryption keys match the restored data. Then start the app: