cms.c2sgmbh/scripts/backup/setup-backup.sh
Martin Porwoll a066539129 feat: add automated PostgreSQL backup system with S3 offsite storage
- Add backup-db.sh for daily automated backups via cron
- Add restore-db.sh for interactive database restoration
- Add setup-backup.sh for easy setup on new servers
- Support local and S3 (Hetzner Object Storage) backup locations
- 30-day retention with automatic cleanup
- Credentials stored securely in ~/.pgpass and ~/.s3cfg
- Comprehensive documentation with disaster recovery checklist

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-11 14:10:39 +00:00

293 lines
7.5 KiB
Bash
Executable file

#!/bin/bash
#
# Payload CMS - Backup-System Setup
# Richtet das automatische Backup-System auf einem neuen Server ein.
#
# Verwendung:
# ./setup-backup.sh
#
# Voraussetzungen:
# - PostgreSQL-Client (psql, pg_dump) installiert
# - Zugriff auf die Datenbank
#
set -euo pipefail
# ============================================================================
# Konfiguration
# ============================================================================
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
BACKUP_DIR="/home/payload/backups/postgres"
LOG_DIR="/home/payload/logs"
# ============================================================================
# Funktionen
# ============================================================================
print_header() {
echo ""
echo "=============================================="
echo " Payload CMS - Backup-System Setup"
echo "=============================================="
echo ""
}
print_step() {
echo "[$(date '+%H:%M:%S')] $1"
}
print_success() {
echo "[✓] $1"
}
print_error() {
echo "[✗] ERROR: $1" >&2
}
check_prerequisites() {
print_step "Prüfe Voraussetzungen..."
if ! command -v psql &> /dev/null; then
print_error "psql nicht gefunden. Installiere mit: apt install postgresql-client"
exit 1
fi
if ! command -v pg_dump &> /dev/null; then
print_error "pg_dump nicht gefunden. Installiere mit: apt install postgresql-client"
exit 1
fi
print_success "PostgreSQL-Client verfügbar"
}
setup_directories() {
print_step "Erstelle Verzeichnisse..."
mkdir -p "$BACKUP_DIR"
mkdir -p "$LOG_DIR"
print_success "Verzeichnisse erstellt"
}
setup_pgpass() {
local pgpass_file="$HOME/.pgpass"
print_step "Konfiguriere PostgreSQL-Authentifizierung..."
if [[ -f "$pgpass_file" ]]; then
echo " .pgpass existiert bereits."
read -p " Überschreiben? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_success ".pgpass beibehalten"
return 0
fi
fi
echo ""
echo " PostgreSQL-Verbindungsdaten eingeben:"
read -p " Host [10.10.181.101]: " db_host
db_host=${db_host:-10.10.181.101}
read -p " Port [5432]: " db_port
db_port=${db_port:-5432}
read -p " Datenbank [payload_db]: " db_name
db_name=${db_name:-payload_db}
read -p " Benutzer [payload]: " db_user
db_user=${db_user:-payload}
read -sp " Passwort: " db_pass
echo ""
if [[ -z "$db_pass" ]]; then
print_error "Passwort darf nicht leer sein"
exit 1
fi
echo "${db_host}:${db_port}:${db_name}:${db_user}:${db_pass}" > "$pgpass_file"
chmod 600 "$pgpass_file"
print_success ".pgpass erstellt (chmod 600)"
# Test connection
print_step "Teste Datenbankverbindung..."
if psql -h "$db_host" -p "$db_port" -U "$db_user" -d "$db_name" -c "SELECT 1" > /dev/null 2>&1; then
print_success "Datenbankverbindung erfolgreich"
else
print_error "Datenbankverbindung fehlgeschlagen"
exit 1
fi
}
setup_s3() {
local s3cfg_file="$HOME/.s3cfg"
print_step "Konfiguriere S3 Offsite-Backup..."
read -p " S3 Offsite-Backup aktivieren? [Y/n] " -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_success "S3-Backup übersprungen"
return 0
fi
# Check if s3cmd is installed
if ! command -v s3cmd &> /dev/null; then
echo " s3cmd nicht gefunden. Installiere..."
if command -v apt &> /dev/null; then
sudo apt update && sudo apt install -y s3cmd
else
print_error "Bitte s3cmd manuell installieren"
return 1
fi
fi
if [[ -f "$s3cfg_file" ]]; then
echo " .s3cfg existiert bereits."
read -p " Überschreiben? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_success ".s3cfg beibehalten"
return 0
fi
fi
echo ""
echo " S3-Verbindungsdaten eingeben:"
read -p " S3 Host (z.B. fsn1.your-objectstorage.com): " s3_host
if [[ -z "$s3_host" ]]; then
print_error "S3 Host darf nicht leer sein"
return 1
fi
read -p " Access Key: " s3_access_key
read -sp " Secret Key: " s3_secret_key
echo ""
if [[ -z "$s3_access_key" || -z "$s3_secret_key" ]]; then
print_error "Access Key und Secret Key dürfen nicht leer sein"
return 1
fi
cat > "$s3cfg_file" << EOF
[default]
access_key = ${s3_access_key}
secret_key = ${s3_secret_key}
host_base = ${s3_host}
host_bucket = %(bucket)s.${s3_host}
use_https = True
signature_v2 = False
EOF
chmod 600 "$s3cfg_file"
print_success ".s3cfg erstellt (chmod 600)"
# Test S3 connection
print_step "Teste S3-Verbindung..."
if s3cmd ls > /dev/null 2>&1; then
print_success "S3-Verbindung erfolgreich"
s3cmd ls
else
print_error "S3-Verbindung fehlgeschlagen"
return 1
fi
}
install_backup_script() {
print_step "Installiere Backup-Skript..."
local source_script="${SCRIPT_DIR}/backup-db.sh"
local target_script="${BACKUP_DIR}/backup-db.sh"
if [[ ! -f "$source_script" ]]; then
print_error "Backup-Skript nicht gefunden: $source_script"
exit 1
fi
cp "$source_script" "$target_script"
chmod +x "$target_script"
print_success "Backup-Skript installiert: $target_script"
}
setup_cron() {
print_step "Konfiguriere Cron-Job..."
local cron_entry="0 3 * * * ${BACKUP_DIR}/backup-db.sh >> ${LOG_DIR}/backup-cron.log 2>&1"
# Check if cron entry already exists
if crontab -l 2>/dev/null | grep -q "backup-db.sh"; then
echo " Cron-Job existiert bereits."
read -p " Überschreiben? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_success "Cron-Job beibehalten"
return 0
fi
# Remove existing entry
crontab -l 2>/dev/null | grep -v "backup-db.sh" | crontab -
fi
# Add new cron entry
(crontab -l 2>/dev/null; echo "# Payload CMS - Tägliches PostgreSQL Backup"; echo "$cron_entry") | crontab -
print_success "Cron-Job eingerichtet (täglich um 03:00 Uhr)"
}
test_backup() {
print_step "Teste Backup..."
read -p " Test-Backup jetzt ausführen? [Y/n] " -n 1 -r
echo
if [[ $REPLY =~ ^[Nn]$ ]]; then
print_success "Test übersprungen"
return 0
fi
if "${BACKUP_DIR}/backup-db.sh" --verbose; then
print_success "Test-Backup erfolgreich"
else
print_error "Test-Backup fehlgeschlagen"
exit 1
fi
}
print_summary() {
echo ""
echo "=============================================="
echo " Setup abgeschlossen!"
echo "=============================================="
echo ""
echo " Backup-Skript: ${BACKUP_DIR}/backup-db.sh"
echo " Lokale Backups: ${BACKUP_DIR}/"
echo " Log-Dateien: ${BACKUP_DIR}/backup.log"
echo " ${LOG_DIR}/backup-cron.log"
echo ""
echo " Cron-Job: Täglich um 03:00 Uhr"
echo ""
echo " Manuelle Ausführung:"
echo " ${BACKUP_DIR}/backup-db.sh --verbose"
echo ""
}
# ============================================================================
# Hauptprogramm
# ============================================================================
main() {
print_header
check_prerequisites
setup_directories
setup_pgpass
setup_s3
install_backup_script
setup_cron
test_backup
print_summary
}
main "$@"