Backup and Restore Guide
This guide provides comprehensive documentation for backing up, restoring, and migrating database records and media assets in the containerized Scannersky stack.
Architecture Overview & Default Paths
In the Docker deployment stack:
- Database (
postgres:16): Data is stored inside container volumepostgres_data. Backups are generated via containerizedpg_dumpcommands directly inside thepostgrescontainer. - Media Assets (
minio:latest): Uploaded student photos (persons/), digital signatures (signatures/), profile pictures (profiles/), and rendered badges (id_cards/) are stored in thescannersky-mediaMinIO object storage bucket. - Zero Host Dependencies: Neither PostgreSQL nor MinIO client utilities are required on the host OS; all operations run through containerized bash scripts in
deploy/scripts/.
Default Backup Paths
When no custom paths are specified, all backup and restore operations default to your user home directory (~/):
- Database Backup Root:
~/db_backups/postgres_dumps/ - Media Backup Root:
~/media_backups/media/
1. Automated Backup Workflow
The backup script [deploy/scripts/backup-docker.sh] supports backing up database dumps, MinIO media assets, or both.
Backup Commands
# 1. Backup MEDIA ONLY (exports MinIO bucket into single-instance ~/media_backups/media/)
bash ./deploy/scripts/backup-docker.sh --media-only
# 2. Backup DATABASE ONLY (exports PostgreSQL dump into ~/db_backups/postgres_dumps/scannersky_YYYYMMDD_HHMMSS.sql)
bash ./deploy/scripts/backup-docker.sh --db-only
# 3. Backup BOTH Database & Media (default)
bash ./deploy/scripts/backup-docker.sh --all
Single-Instance Media Backup Behavior
To prevent disk space exhaustion from duplicate media archives, media backups maintain a single active instance at ~/media_backups/media/:
- Automatic Overwrite: Each time
backup-docker.sh(or--media-only) runs, it overwrites the previous media copy in~/media_backups/media/with the latest files from the MinIOscannersky-mediabucket. - Metadata Timestamping: Writes a
.backup_infometadata file into~/media_backups/media/.backup_inforecording the exact creation date and time (BACKUP_DATEandBACKUP_TIMESTAMP).
Database Dump Retention Policy
PostgreSQL SQL dumps are saved with timestamps: ~/db_backups/postgres_dumps/scannersky_YYYYMMDD_HHMMSS.sql.
- Retention: Old
.sqldump files older than 7 days are automatically purged during backup execution (configurable viaRETENTION_DAYS).
Automated Nightly Crontab Schedule
To enable automated nightly backups at 2:00 AM, add this entry to your system crontab (crontab -e):
0 2 * * * ~/scannersky-django/deploy/scripts/backup-docker.sh >> ~/db_backups/backup.log 2>&1
2. Unified Restoration Workflow
The restoration script [deploy/scripts/restore-docker.sh] provides interactive database selection and media date/time confirmation:
# 1. Restore BOTH database and media in one step (Recommended)
bash ./deploy/scripts/restore-docker.sh --all
# 2. Restore PostgreSQL database dump only
bash ./deploy/scripts/restore-docker.sh --db-only
# 3. Restore Media backup directory into MinIO bucket only
bash ./deploy/scripts/restore-docker.sh --media-only
3. Interactive Database Restoration (--db-only)
Interactive Dump Selection Menu
When DUMP_FILE is not specified, restore-docker.sh scans ~/db_backups/postgres_dumps/, lists available SQL dump files with file sizes and creation timestamps, and presents an interactive choice menu:
=== Available Database Dumps ===
1) scannersky_20260807_143000.sql (12.4 MB) - [Aug 07 14:30]
2) scannersky_20260805_015853.sql (11.8 MB) - [Aug 05 01:58]
Select dump number [1-2] (default: 1):
- Pressing
Enter(or selecting1) automatically chooses the latest valid dump file. - Typing a number selects that specific dump.
- Entering a file path uses that specific custom SQL file.
Confirmation Prompt & Execution
Before modifying the database, the script displays the target dump details and asks for confirmation:
=== Database Restore ===
Target Database: scannersky
Dump File: /home/scannersking/db_backups/postgres_dumps/scannersky_20260807_143000.sql (12.4 MB) - [Aug 07 14:30]
Continue restoring database from scannersky_20260807_143000.sql? [y/N]: y
During restoration:
- Executes
DROP DATABASE IF EXISTS "scannersky" WITH (FORCE);to safely terminate all active Django connections. - Recreates the
scannerskydatabase. - Streams the SQL dump directly into the containerized
postgresinstance.
4. Media Restoration Details (--media-only)
The media migration script [deploy/scripts/restore-media.sh] restores media files from ~/media_backups/media/ into the MinIO scannersky-media bucket.
Timestamp Confirmation Prompt
Before importing files, the script reads the backup timestamp from ~/media_backups/media/.backup_info (or directory modification date) and prompts for confirmation:
=== MinIO Media Restoration ===
Source directory: /home/scannersking/media_backups/media
Backup Date/Time: Fri Aug 7 14:30:00 PST 2026
Target Bucket: scannersky-media
Continue restoring media backup from [Fri Aug 7 14:30:00 PST 2026]? [y/N]: y
Support for Legacy
/media/Copies
If a media folder was copied directly from an old non-containerized installation (without a.backup_infometadata file),restore-media.shautomatically reads the folder's file modification timestamp and imports all subdirectories (persons/,signatures/,profiles/,id_cards/,syllabi/) cleanly into MinIO.
MinIO Import & Access Policy
During restoration:
- Copies backup files into the
miniocontainer usingdocker cp. - Runs MinIO Client (
mc mirror --overwrite) to mirror all subdirectories (persons/,signatures/,profiles/,id_cards/,syllabi/) into bucketscannersky-media. - Sets public download access (
mc anonymous set download local/scannersky-media) so Nginx can proxy images without requiring signed URLs.
5. Custom Path Overrides
You can pass custom dump file or media directory paths on disk using DUMP_FILE and MEDIA_DIR:
# Custom SQL Dump File Location
DUMP_FILE="/mnt/external_drive/backups/db_july.sql" bash ./deploy/scripts/restore-docker.sh --db-only
# Custom Media Backup Directory Location
MEDIA_DIR="/mnt/usb/media_backup_2026" bash ./deploy/scripts/restore-docker.sh --media-only
# Combined Custom Restore
DUMP_FILE="/tmp/custom_db.sql" MEDIA_DIR="/tmp/custom_media" bash ./deploy/scripts/restore-docker.sh --all
6. Post-Restore Verification Checklist
After running any restore operation, run the production validation suite to confirm system health:
bash ./deploy/scripts/validate-production.sh
Expected Output:
=== Production validation ===
[0/6] run Django deploy check --> OK
[1/6] check services are healthy --> OK (postgres, minio, django, nginx, mcp)
[2/6] curl /health/ (200 OK) --> OK
[3/6] check static stylesheet via Nginx --> OK
[4/6] check media bucket public path --> OK
[5/6] check admin login page --> OK
[6/6] check API root --> OK
[7/7] check Docusaurus docs site --> OK
=== Validation result: 0 failure(s) ===
Deployment Script Summary
| Script File | Primary Purpose | Key Default Paths |
|---|---|---|
deploy/scripts/backup-docker.sh | Generates DB dumps & single-instance media backup | ~/db_backups/postgres_dumps/, ~/media_backups/media/ |
deploy/scripts/restore-docker.sh | Interactive DB restore & unified entrypoint | DUMP_FILE (Interactive selection) |
deploy/scripts/restore-media.sh | MinIO media bucket importer with date/time confirmation | ~/media_backups/media/ |
deploy/scripts/setup-minio.sh | MinIO bucket provisioner | scannersky-media, scannersky-static |
deploy/scripts/validate-production.sh | End-to-end production health validation | http://127.0.0.1/health/ |