3-2-1 Backup-Strategie

Backups die nicht getestet wurden sind keine Backups. Das klingt nach Klischee bis man ein Backup zurückspielen muss und feststellt dass es seit zwei Monaten leer ist.

Die 3-2-1-Regel

  • 3 Kopien der Daten
  • auf 2 verschiedenen Medien/Systemen
  • davon 1 Off-Site

Konkret: Produktivdatenbank, Backup auf demselben Server, Backup auf einem anderen Server oder in Cloud-Storage.

Datenbankbackup automatisieren

#!/bin/bash
set -euo pipefail

DB_NAME="myapp"
BACKUP_DIR="/backup/db"
TIMESTAMP=$(date +%Y-%m-%d_%H-%M)
FILE="$BACKUP_DIR/${DB_NAME}_${TIMESTAMP}.sql.gz"

mkdir -p "$BACKUP_DIR"

mysqldump \
    --single-transaction \
    --quick \
    --lock-tables=false \
    "$DB_NAME" | gzip > "$FILE"

# Alte Backups löschen (>30 Tage)
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +30 -delete

# Erfolg melden
curl -fsS "https://hc-ping.com/${HEALTHCHECK_UUID}" > /dev/null

--single-transaction macht ein konsistentes Backup ohne Tabellen zu sperren — für InnoDB wichtig.

Dateien mit rsync Off-Site

rsync -az --delete \
    /backup/ \
    backup-user@offsite-server:/backup/myapp/

Rclone für Cloud-Storage

rclone copy /backup s3:my-bucket/backups \
    --transfers 4 \
    --s3-storage-class STANDARD_IA   # günstiger für selten abgerufene Daten

Funktioniert mit S3, Backblaze B2, Hetzner Object Storage und Dutzenden anderen Anbietern.

Verschlüsselung

# Backup verschlüsseln bevor Upload
gpg --batch --yes \
    --recipient backup@example.com \
    --encrypt "$FILE"

# Unverschlüsseltes Backup lokal löschen
rm "$FILE"

Off-Site-Backups sollten immer verschlüsselt sein — man gibt sie aus der Hand.

Restore testen

Einmal pro Monat ein Backup zurückspielen. In eine Testdatenbank, nicht in Produktion.

# Test-Restore
gunzip < backup_2023-07-24.sql.gz | mysql myapp_test
mysql myapp_test -e "SELECT COUNT(*) FROM users;"

Ein Backup das man nie restored hat ist eine Hoffnung, kein Plan.