EPPA Backup and Restore Drill Runbook¶
This runbook covers the repository-owned local drill for EPPA Postgres and MinIO data. It is designed to prove the backup/restore path with synthetic fixtures and without production credentials.
Safety Model¶
- Backup output must be written to
EPPA_BACKUP_DIR, and the script refuses any directory inside this Git repository. - Restore drill only runs against local service hosts:
127.0.0.1,localhost,postgres, orminio. - Restore drill refuses to run when
EPPA_ENVorENVIRONMENTisprodorproduction. - Restore drill requires both explicit non-production flags:
EPPA_RESTORE_TARGET=local-drillandEPPA_ALLOW_DESTRUCTIVE_RESTORE=YES_I_UNDERSTAND_NON_PRODUCTION. - Synthetic fixtures contain no patient data. They are limited to a probe SQL row and a JSON object labeled as synthetic.
Environment¶
Default local values match docker-compose.yml:
export EPPA_BACKUP_DIR=/tmp/eppa-backups
export DATABASE_URL='postgresql+psycopg://eppa:eppa_dev_pw_CHANGE_ME@127.0.0.1:5432/eppa'
export EPPA_MINIO_ENDPOINT='http://127.0.0.1:9000'
export EPPA_MINIO_ACCESS_KEY='eppa_minio_admin'
export EPPA_MINIO_SECRET_KEY='eppa_minio_dev_pw_CHANGE_ME'
export EPPA_MINIO_BUCKET='eppa-restore-drill'
Use deployment secrets only on the server and never paste them into issues, PRs, logs, or committed files.
Dry Run¶
Dry run validates output placement and writes only synthetic placeholders:
cd fronts/eppa
EPPA_BACKUP_DIR=/tmp/eppa-backups \
python3 scripts/backup_restore_drill.py --dry-run backup
For the restore safety path:
cd fronts/eppa
EPPA_BACKUP_DIR=/tmp/eppa-backups \
EPPA_ENV=test \
EPPA_RESTORE_TARGET=local-drill \
EPPA_ALLOW_DESTRUCTIVE_RESTORE=YES_I_UNDERSTAND_NON_PRODUCTION \
python3 scripts/backup_restore_drill.py --dry-run restore-drill
Local Restore Drill¶
Start fresh local services:
cd fronts/eppa
docker compose up -d postgres minio
docker compose ps postgres minio
Load the synthetic drill dataset:
EPPA_BACKUP_DIR=/tmp/eppa-backups \
EPPA_ENV=test \
EPPA_RESTORE_TARGET=local-drill \
EPPA_ALLOW_DESTRUCTIVE_RESTORE=YES_I_UNDERSTAND_NON_PRODUCTION \
DATABASE_URL='postgresql+psycopg://eppa:eppa_dev_pw_CHANGE_ME@127.0.0.1:5432/eppa' \
EPPA_MINIO_ENDPOINT='http://127.0.0.1:9000' \
EPPA_MINIO_ACCESS_KEY='eppa_minio_admin' \
EPPA_MINIO_SECRET_KEY='eppa_minio_dev_pw_CHANGE_ME' \
EPPA_MINIO_BUCKET='eppa-restore-drill' \
python3 scripts/backup_restore_drill.py restore-drill
The command creates or updates eppa_restore_drill_probe in Postgres and
uploads restore-drill/synthetic-eppa-minio-001.json to the configured MinIO
bucket.
Backup¶
Run a local backup into an external directory:
cd fronts/eppa
EPPA_BACKUP_DIR=/tmp/eppa-backups \
DATABASE_URL='postgresql+psycopg://eppa:eppa_dev_pw_CHANGE_ME@127.0.0.1:5432/eppa' \
EPPA_MINIO_ENDPOINT='http://127.0.0.1:9000' \
EPPA_MINIO_ACCESS_KEY='eppa_minio_admin' \
EPPA_MINIO_SECRET_KEY='eppa_minio_dev_pw_CHANGE_ME' \
EPPA_MINIO_BUCKET='eppa-restore-drill' \
python3 scripts/backup_restore_drill.py backup
Each run creates a timestamped directory containing:
postgres.dump:pg_dump --format=customoutput.minio/: downloaded MinIO object files for the configured bucket/prefix.postgres-synthetic.sqlandminio-synthetic-object.json: non-sensitive fixtures used by the drill.manifest.json: operation metadata and acontains_real_patient_data: falsedeclaration for the synthetic fixtures.
Retention Assumptions¶
- Keep local drill outputs short-lived. Delete
/tmp/eppa-backupsafter the drill unless an audit packet explicitly needs the manifest. - Production retention policy is outside this repository-owned script and must be enforced by the production storage target.
- Do not copy production backup artifacts into the Git repository.