All checks were successful
Basil CI/CD Pipeline / Shared Package Tests (push) Successful in 1m10s
Basil CI/CD Pipeline / Code Linting (push) Successful in 1m18s
Basil CI/CD Pipeline / Web Tests (push) Successful in 1m29s
Basil CI/CD Pipeline / Security Scanning (push) Successful in 1m14s
Basil CI/CD Pipeline / API Tests (push) Successful in 1m45s
Basil CI/CD Pipeline / Trigger Deployment (push) Successful in 12s
Basil CI/CD Pipeline / Build All Packages (push) Successful in 1m31s
Basil CI/CD Pipeline / E2E Tests (push) Has been skipped
Basil CI/CD Pipeline / Build & Push Docker Images (push) Successful in 14m27s
Added production-grade backup and restore scripts for PostgreSQL servers
that can backup all databases automatically with retention management.
New scripts:
- scripts/backup-all-postgres-databases.sh - Backs up all databases on a
PostgreSQL server with automatic retention, compression, verification,
and notification support
- scripts/restore-postgres-database.sh - Restores individual databases
with safety backups and verification
- scripts/README-POSTGRES-BACKUP.md - Complete documentation with examples,
best practices, and troubleshooting
Features:
- Automatic detection and backup of all user databases
- Excludes system databases (postgres, template0, template1)
- Backs up global objects (roles, tablespaces)
- Optional gzip compression (80-90% space savings)
- Automatic retention management (configurable days)
- Integrity verification (gzip -t for compressed files)
- Safety backups before restore operations
- Detailed logging with color-coded output
- Backup summary reporting
- Email/Slack notification support (optional)
- Interactive restore with confirmation prompts
- Force mode for automation
- Verbose debugging mode
- Comprehensive error handling
Backup directory structure:
/var/backups/postgresql/YYYYMMDD/
- globals_YYYYMMDD_HHMMSS.sql.gz
- database1_YYYYMMDD_HHMMSS.sql.gz
- database2_YYYYMMDD_HHMMSS.sql.gz
Usage examples:
# Backup all databases with compression
./backup-all-postgres-databases.sh -c
# Custom configuration
./backup-all-postgres-databases.sh -h db.server.com -U backup_user -d /mnt/backups -r 60 -c
# Restore database
./restore-postgres-database.sh /var/backups/postgresql/20260120/mydb_20260120_020001.sql.gz
# Force restore (skip confirmation)
./restore-postgres-database.sh backup.sql.gz -d mydb -f
Automation:
# Add to crontab for daily backups at 2 AM
0 2 * * * /path/to/backup-all-postgres-databases.sh -c >> /var/log/postgres-backup.log 2>&1
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9.7 KiB
9.7 KiB
PostgreSQL Backup Scripts
Comprehensive backup and restore scripts for PostgreSQL databases.
Scripts Overview
1. backup-all-postgres-databases.sh
Backs up all databases on a PostgreSQL server (excluding system databases).
Features:
- ✅ Backs up all user databases automatically
- ✅ Includes global objects (roles, tablespaces)
- ✅ Optional gzip compression
- ✅ Automatic retention management
- ✅ Integrity verification
- ✅ Detailed logging with color output
- ✅ Backup summary reporting
- ✅ Email/Slack notification support (optional)
2. restore-postgres-database.sh
Restores a single database from backup.
Features:
- ✅ Safety backup before restore
- ✅ Interactive confirmation
- ✅ Automatic database name detection
- ✅ Compressed file support
- ✅ Integrity verification
- ✅ Post-restore verification
Quick Start
Backup All Databases
# Basic usage
./backup-all-postgres-databases.sh
# With compression (recommended)
./backup-all-postgres-databases.sh -c
# Custom configuration
./backup-all-postgres-databases.sh \
-h db.example.com \
-U postgres \
-d /mnt/backups \
-r 60 \
-c
Restore a Database
# Interactive restore (with confirmation)
./restore-postgres-database.sh /var/backups/postgresql/20260120/mydb_20260120_020001.sql.gz
# Force restore (skip confirmation)
./restore-postgres-database.sh backup.sql.gz -d mydb -f
Detailed Usage
Backup Script Options
./backup-all-postgres-databases.sh [options]
Options:
-h HOST Database host (default: localhost)
-p PORT Database port (default: 5432)
-U USER Database user (default: postgres)
-d BACKUP_DIR Backup directory (default: /var/backups/postgresql)
-r DAYS Retention days (default: 30)
-c Enable compression (gzip)
-v Verbose output
-H Show help
Restore Script Options
./restore-postgres-database.sh <backup_file> [options]
Options:
-h HOST Database host (default: localhost)
-p PORT Database port (default: 5432)
-U USER Database user (default: postgres)
-d DBNAME Target database name (default: from filename)
-f Force restore (skip confirmation)
-v Verbose output
-H Show help
Automated Backups with Cron
Daily Backups (Recommended)
# Edit crontab
sudo crontab -e
# Add daily backup at 2 AM with compression
0 2 * * * /path/to/backup-all-postgres-databases.sh -c >> /var/log/postgres-backup.log 2>&1
Alternative Schedules
# Every 6 hours
0 */6 * * * /path/to/backup-all-postgres-databases.sh -c
# Twice daily (2 AM and 2 PM)
0 2,14 * * * /path/to/backup-all-postgres-databases.sh -c
# Weekly on Sundays at 3 AM
0 3 * * 0 /path/to/backup-all-postgres-databases.sh -c -r 90
Backup Directory Structure
/var/backups/postgresql/
├── 20260120/ # Date-based subdirectory
│ ├── globals_20260120_020001.sql.gz # Global objects backup
│ ├── basil_20260120_020001.sql.gz # Database backup
│ ├── myapp_20260120_020001.sql.gz # Database backup
│ └── wiki_20260120_020001.sql.gz # Database backup
├── 20260121/
│ ├── globals_20260121_020001.sql.gz
│ └── ...
└── 20260122/
└── ...
Configuration Examples
Local PostgreSQL Server
./backup-all-postgres-databases.sh \
-h localhost \
-U postgres \
-c
Remote PostgreSQL Server
./backup-all-postgres-databases.sh \
-h db.example.com \
-p 5432 \
-U backup_user \
-d /mnt/network/backups \
-r 60 \
-c \
-v
High-Frequency Backups
# Short retention for frequent backups
./backup-all-postgres-databases.sh \
-r 7 \
-c
Authentication Setup
Option 1: .pgpass File (Recommended)
Create ~/.pgpass with connection credentials:
echo "localhost:5432:*:postgres:your-password" >> ~/.pgpass
chmod 600 ~/.pgpass
Format: hostname:port:database:username:password
Option 2: Environment Variables
export PGPASSWORD="your-password"
./backup-all-postgres-databases.sh
Option 3: Peer Authentication (Local Only)
Run as the postgres system user:
sudo -u postgres ./backup-all-postgres-databases.sh
Monitoring and Notifications
Email Notifications
Edit the scripts and uncomment the email notification section:
# In backup-all-postgres-databases.sh, uncomment:
if command -v mail &> /dev/null; then
echo "$summary" | mail -s "PostgreSQL Backup $status - $(hostname)" admin@example.com
fi
Slack Notifications
Set webhook URL and uncomment:
export SLACK_WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
# In script, uncomment:
if [ -n "$SLACK_WEBHOOK_URL" ]; then
curl -X POST "$SLACK_WEBHOOK_URL" \
-H 'Content-Type: application/json' \
-d "{\"text\":\"PostgreSQL Backup $status\n$summary\"}"
fi
Log Rotation
Create /etc/logrotate.d/postgres-backup:
/var/log/postgres-backup.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
}
Backup Verification
Manual Verification
# List backups
ls -lh /var/backups/postgresql/$(date +%Y%m%d)/
# Verify compressed file integrity
gzip -t /var/backups/postgresql/20260120/basil_20260120_020001.sql.gz
# Preview backup contents
gunzip -c backup.sql.gz | head -50
Test Restore (Recommended Monthly)
# Restore to a test database
./restore-postgres-database.sh backup.sql.gz -d test_restore -f
# Verify
psql -d test_restore -c "\dt"
# Cleanup
dropdb test_restore
Disaster Recovery
Full Server Restore
- Install PostgreSQL on new server
- Restore global objects first:
gunzip -c globals_YYYYMMDD_HHMMSS.sql.gz | psql -U postgres -d postgres - Restore each database:
./restore-postgres-database.sh basil_20260120_020001.sql.gz ./restore-postgres-database.sh myapp_20260120_020001.sql.gz
Point-in-Time Recovery
For PITR capabilities, enable WAL archiving in postgresql.conf:
wal_level = replica
archive_mode = on
archive_command = 'cp %p /var/lib/postgresql/wal_archive/%f'
max_wal_senders = 3
Then use pg_basebackup and WAL replay for PITR.
Troubleshooting
Permission Denied
# Fix backup directory permissions
sudo chown -R postgres:postgres /var/backups/postgresql
sudo chmod 755 /var/backups/postgresql
# Fix script permissions
chmod +x backup-all-postgres-databases.sh
Connection Failed
# Test connection manually
psql -h localhost -U postgres -c "SELECT version();"
# Check pg_hba.conf
sudo cat /etc/postgresql/*/main/pg_hba.conf
# Ensure proper authentication line exists:
# local all postgres peer
# host all all 127.0.0.1/32 scram-sha-256
Out of Disk Space
# Check disk usage
df -h /var/backups
# Clean old backups manually
find /var/backups/postgresql -type d -name "????????" -mtime +30 -exec rm -rf {} \;
# Reduce retention period
./backup-all-postgres-databases.sh -r 7
Backup File Corrupted
# Verify integrity
gzip -t backup.sql.gz
# If corrupted, use previous backup
ls -lt /var/backups/postgresql/*/basil_*.sql.gz | head
Performance Optimization
Large Databases
For very large databases, consider:
# Parallel dump (PostgreSQL 9.3+)
pg_dump -Fd -j 4 -f backup_directory mydb
# Custom format (smaller, faster restore)
pg_dump -Fc mydb > backup.custom
# Restore from custom format
pg_restore -d mydb backup.custom
Network Backups
# Direct SSH backup (no local storage)
pg_dump mydb | gzip | ssh backup-server "cat > /backups/mydb.sql.gz"
Best Practices
- Always test restores - Backups are worthless if you can't restore
- Monitor backup completion - Set up alerts for failed backups
- Use compression - Saves 80-90% of disk space
- Multiple backup locations - Local + remote/cloud storage
- Verify backup integrity - Run gzip -t on compressed backups
- Document procedures - Keep runbooks for disaster recovery
- Encrypt sensitive backups - Use gpg for encryption if needed
- Regular retention review - Adjust based on compliance requirements
Security Considerations
Encryption at Rest
# Encrypt backup with GPG
pg_dump mydb | gzip | gpg --encrypt --recipient admin@example.com > backup.sql.gz.gpg
# Decrypt for restore
gpg --decrypt backup.sql.gz.gpg | gunzip | psql mydb
Secure Transfer
# Use SCP with key authentication
scp -i ~/.ssh/backup_key backup.sql.gz backup-server:/secure/backups/
# Or rsync over SSH
rsync -av -e "ssh -i ~/.ssh/backup_key" \
/var/backups/postgresql/ \
backup-server:/secure/backups/
Access Control
# Restrict backup directory permissions
chmod 700 /var/backups/postgresql
chown postgres:postgres /var/backups/postgresql
# Restrict script permissions
chmod 750 backup-all-postgres-databases.sh
chown root:postgres backup-all-postgres-databases.sh
Additional Resources
Support
For issues or questions:
- Check script help:
./backup-all-postgres-databases.sh -H - Review logs:
tail -f /var/log/postgres-backup.log - Test connection:
psql -h localhost -U postgres