Backup and Recovery¶
Comprehensive guide for protecting your security data and recovering from failures.
Time to read: ~10 min Prerequisites: Container Setup
What to Back Up¶
The Home Security Intelligence system stores data in multiple locations:
| Data Type | Location | Priority |
|---|---|---|
| PostgreSQL Database | postgres_data volume | Critical |
| Generated Media | ./backend/data/ | High |
| Configuration | .env | Critical |
| Camera FTP Uploads | ${FOSCAM_BASE_PATH:-/export/foscam} | Medium |
[!NOTE] Redis is ephemeral cache - it does not require backup.
Database Tables¶
| Table | Description |
|---|---|
cameras | Camera configuration and status |
events | Security events with AI analysis |
detections | Object detection results |
alerts | Alert history and status |
alert_rules | User-defined alert rules |
zones | Camera zone definitions |
activity_baselines | Anomaly detection baselines |
class_baselines | Object class frequency baselines |
audit_logs | Security audit trail |
gpu_stats | GPU performance history |
api_keys | API authentication keys |
Quick Backup Commands¶
Database Backup¶
# Docker - compressed custom format (recommended)
docker compose -f docker-compose.prod.yml exec -T postgres pg_dump -U security -d security \
--format=custom --compress=9 \
> backup_$(date +%Y%m%d).dump
# Podman
podman-compose -f docker-compose.prod.yml exec -T postgres pg_dump -U security -d security \
--format=custom --compress=9 \
> backup_$(date +%Y%m%d).dump
# Plain SQL format
docker compose -f docker-compose.prod.yml exec -T postgres pg_dump -U security security > backup.sql
File Backup¶
# Full generated media directory (thumbnails, clips, logs, etc.)
tar -czvf files_$(date +%Y%m%d).tar.gz backend/data/
# Clips only (if you generate/store clips)
tar -czvf clips_$(date +%Y%m%d).tar.gz backend/data/clips/ || true
Configuration Backup¶
Daily Automated Backup¶
Create /opt/hsi-backup/backup.sh:
#!/bin/bash
set -euo pipefail
BACKUP_DIR="/opt/hsi-backup/daily"
RETENTION_DAYS=30
DATE=$(date +%Y-%m-%d_%H%M%S)
PROJECT_DIR="/path/to/home_security_intelligence"
mkdir -p "${BACKUP_DIR}"
echo "[$(date)] Starting backup..."
# Database
docker compose -f "${PROJECT_DIR}/docker-compose.prod.yml" exec -T postgres pg_dump -U security -d security \
--format=custom --compress=9 \
> "${BACKUP_DIR}/database_${DATE}.dump"
# Files
tar -czf "${BACKUP_DIR}/files_${DATE}.tar.gz" \
-C "${PROJECT_DIR}/backend" data/ \
--exclude='data/logs/*.log.*'
# Config
tar -czf "${BACKUP_DIR}/config_${DATE}.tar.gz" \
-C "${PROJECT_DIR}" .env
# Cleanup old backups
find "${BACKUP_DIR}" -name "*.dump" -mtime +${RETENTION_DAYS} -delete
find "${BACKUP_DIR}" -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date)] Backup complete"
Schedule with cron:
chmod +x /opt/hsi-backup/backup.sh
# Add to crontab - runs daily at 2 AM
0 2 * * * /opt/hsi-backup/backup.sh >> /var/log/hsi-backup.log 2>&1
Recovery Procedures¶
Full System Recovery¶
Estimated time: 30-60 minutes
- Install prerequisites and clone repo
- Restore configuration
- Start database
docker compose -f docker-compose.prod.yml up -d postgres redis
# Wait for healthy
docker compose -f docker-compose.prod.yml ps
- Restore database
docker compose -f docker-compose.prod.yml exec -T postgres pg_restore \
-U security -d security --clean --if-exists \
< backup.dump
- Restore files
- Start all services
- Verify
Database-Only Recovery¶
# Stop backend
docker compose -f docker-compose.prod.yml stop backend
# Drop and recreate database
docker compose -f docker-compose.prod.yml exec -T postgres psql -U security -c "DROP DATABASE security;"
docker compose -f docker-compose.prod.yml exec -T postgres psql -U security -c "CREATE DATABASE security;"
# Restore
docker compose -f docker-compose.prod.yml exec -T postgres pg_restore -U security -d security < backup.dump
# Restart
docker compose -f docker-compose.prod.yml up -d backend
File-Only Recovery¶
docker compose -f docker-compose.prod.yml stop backend
tar -xzf files_backup.tar.gz -C backend/
chown -R 1000:1000 backend/data/
docker compose -f docker-compose.prod.yml up -d backend
Disaster Recovery Checklist¶
Pre-Recovery¶
- [ ] Backup files accessible and verified
- [ ] New server meets requirements
- [ ] Docker/Podman + NVIDIA Container Toolkit installed
- [ ] Sufficient storage space
Recovery Steps¶
- [ ] Clone repository
- [ ] Restore
.envconfiguration - [ ] Start PostgreSQL and Redis
- [ ] Verify database containers healthy
- [ ] Restore database from backup
- [ ] Restore file backups
- [ ] Fix file permissions
- [ ] Start all services
- [ ] Verify all containers healthy
Post-Recovery Verification¶
- [ ] API health check:
curl localhost:8000/api/system/health/ready - [ ] Frontend loads:
curl localhost:5173 - [ ] Event count matches expected
- [ ] Camera list correct
- [ ] Detection images load
- [ ] Alert rules present
Backup Verification¶
Test backups regularly:
# Verify backup structure
pg_restore --list backup.dump > /dev/null && echo "OK"
# Check backup size (should be > 1KB)
ls -lh backup.dump
Offsite Backup¶
For disaster recovery, store backups offsite:
# AWS S3
aws s3 sync /opt/hsi-backup/ s3://your-bucket/hsi-backups/
# rsync to remote server
rsync -avz /opt/hsi-backup/ user@remote:/backups/hsi/
Recovery Testing¶
[!IMPORTANT] Test your recovery procedures monthly. An untested backup is not a backup.
- Create a test environment (VM or separate server)
- Restore from backup following full recovery procedure
- Verify data integrity and functionality
- Document results
- Destroy test environment
Next Steps¶
- Database Management - PostgreSQL setup and maintenance
- Data Model - Understanding what is backed up
See Also¶
- Database Troubleshooting - Solve PostgreSQL problems
- Environment Variable Reference - Retention configuration