Skip to main content

Backup Guide

Set up automated backups for Bellamy Book.

In-app backup (admin panel)

The admin panel can run scheduled or manual backups that dump PostgreSQL, MongoDB, Neo4j, and Elasticsearch and upload the archive to object storage. The destination is the same storage provider as media (MinIO or Cloudflare R2). If production uses R2, backups go to the R2 backups bucket automatically — no extra config. See R2 Setup — Backup with R2 for details.

Backup Strategy

Back up:

  • PostgreSQL database
  • MongoDB database
  • Uploaded files
  • Configuration files

PostgreSQL Backups

Manual Backup

pg_dump -U bellamyuser -d bellamybook > backup_$(date +%Y%m%d).sql

Automated Backup Script

Create /usr/local/bin/backup-postgres.sh:

#!/bin/bash
BACKUP_DIR="/backups/postgres"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

pg_dump -U bellamyuser -d bellamybook | gzip > $BACKUP_DIR/backup_$DATE.sql.gz

# Keep only last 30 days
find $BACKUP_DIR -name "backup_*.sql.gz" -mtime +30 -delete

Make it executable:

chmod +x /usr/local/bin/backup-postgres.sh

Cron Job

# Daily backup at 2 AM
0 2 * * * /usr/local/bin/backup-postgres.sh

MongoDB Backups

Manual Backup

mongodump --uri="mongodb://username:password@localhost:27017/bellamybook" --out=/backups/mongo

Automated Backup Script

Create /usr/local/bin/backup-mongo.sh:

#!/bin/bash
BACKUP_DIR="/backups/mongo"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

mongodump --uri="mongodb://username:password@localhost:27017/bellamybook" \
--out=$BACKUP_DIR/backup_$DATE

# Compress
tar -czf $BACKUP_DIR/backup_$DATE.tar.gz -C $BACKUP_DIR backup_$DATE
rm -rf $BACKUP_DIR/backup_$DATE

# Keep only last 30 days
find $BACKUP_DIR -name "backup_*.tar.gz" -mtime +30 -delete

Cron Job

# Daily backup at 3 AM
0 3 * * * /usr/local/bin/backup-mongo.sh

File Backups

Local Storage Backup

#!/bin/bash
BACKUP_DIR="/backups/files"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR

tar -czf $BACKUP_DIR/files_$DATE.tar.gz /var/www/uploads

# Keep only last 7 days
find $BACKUP_DIR -name "files_*.tar.gz" -mtime +7 -delete

S3 Backup

If using S3, enable versioning and lifecycle policies.

Docker Backups

Backup Script

#!/bin/bash
BACKUP_DIR="/backups"
DATE=$(date +%Y%m%d_%H%M%S)

# PostgreSQL
docker exec postgres pg_dump -U postgres bellamybook | gzip > $BACKUP_DIR/postgres_$DATE.sql.gz

# MongoDB
docker exec mongo mongodump --archive | gzip > $BACKUP_DIR/mongo_$DATE.archive.gz

# Files
docker exec frontend tar -czf - /uploads | gzip > $BACKUP_DIR/files_$DATE.tar.gz

Restore Procedures

Restore PostgreSQL

gunzip < backup_20240101.sql.gz | psql -U bellamyuser -d bellamybook

Restore MongoDB

mongorestore --uri="mongodb://username:password@localhost:27017/bellamybook" \
--archive=backup_20240101.archive.gz --gzip

Restore Files

tar -xzf files_20240101.tar.gz -C /

Remote Backup Storage

S3 Backup

Upload backups to S3:

aws s3 cp backup_$DATE.sql.gz s3://your-backup-bucket/postgres/

rsync to Remote Server

rsync -avz /backups user@backup-server:/remote-backups/

Backup Verification

Test Restores

Regularly test restore procedures:

# Test restore to temporary database
createdb test_restore
gunzip < backup.sql.gz | psql -d test_restore
# Verify data
psql -d test_restore -c "SELECT COUNT(*) FROM posts;"
dropdb test_restore

Monitoring

Backup Status Monitoring

Check backup success:

#!/bin/bash
LAST_BACKUP=$(find /backups -name "*.sql.gz" -mtime -1)
if [ -z "$LAST_BACKUP" ]; then
echo "WARNING: No backup found in last 24 hours"
# Send alert
fi

Next Steps