Wie der Homeserver gesichert wird

  • Philipp
  • 3 Min. Lesezeit
Inhalt

Auf dem Raspberry Pi als Homeserver liegt alles auf einer SSD: die Anwendungen, ihre Daten, die Datenbank. Eine Sicherung auf derselben Platte wäre also suboptimal. Für die Dateien der Anwendungen reicht lediglich ein rsync des Verzeichnisses, für die Postgres Datenbanken nicht.

Azure

Homeserver

02:30 pg_dumpall

03:30 restic

up / down

verschlüsselt

Postgres

/mnt/ssd/backups/postgres

Offsite-Dienst

Uptime Kuma

Blob Container
homeserver-backup

Warum ein Dump

Mehrere Anwendungen teilen sich eine Postgres-Instanz, jede mit eigener Datenbank. pg_dumpall schreibt alle davon inklusive der Rollen in eine einzige SQL-Datei. Kommt also eine neue Datenbank dazu, ist sie automatisch mit drin.

Die drei Stufen liegen alle in der service.yaml von Postgres:

StufeDienstFunktionAufbewahrung
1postgres-backup02:30 pg_dumpall nach /mnt/ssd/backups/postgres7 Tage, 4 Wochen, 6 Monate
2postgres-offsite-backup03:30 restic-Snapshot nach Azure, danach restic check14 Tage, 8 Wochen, 12 Monate
3postgres-offsite-backupPush an Uptime Kuma, up oder down-

Stufe 1: Der Dump

Das Image prodrigestivill/postgres-backup-local1 ist genau dafür gemacht.

applications/postgres/service.yaml (gekürzt)
postgres-backup:
  image: prodrigestivill/postgres-backup-local:16
  user: "999:999"
  environment:
    SCHEDULE: "30 2 * * *"
    BACKUP_ON_START: "TRUE"
    POSTGRES_HOST: postgres
    POSTGRES_CLUSTER: "TRUE"
    POSTGRES_PASSWORD_FILE: /run/secrets/postgres_password
    BACKUP_KEEP_DAYS: 7
    BACKUP_KEEP_WEEKS: 4
    BACKUP_KEEP_MONTHS: 6

Im Ergebnis liegen unter daily/, weekly/ und monthly/ die rotierten Dumps und unter last/ immer der Neueste. Diesen Ordner sichert Stufe 2.

Stufe 2: Verschlüsselt nach Azure

Wohin, war schnell entschieden. Eine Azure-Subscription gibt es ohnehin, dieser Blog läuft dort, und beruflich ist Azure natürlich auch mein Alltag. Für ein paar komprimierte SQL-Dateien kostet lokal redundanter Speicher praktisch nichts. Der Storage Account ist eigens dafür angelegt und macht sonst nichts.

restic2 verschlüsselt das Backup auf dem Server, bevor irgendetwas den Homeserver verlässt. Es lädt nur hoch, was sich geändert hat, und definiert die Aufbewahrungsregeln:

sh
restic backup --host homeserver --tag postgres /backups
restic forget --host homeserver --tag postgres --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
restic check

Das check am Ende prüft, ob das Repository in sich stimmig ist. Ein Backup, das sich nicht lesen lässt, soll schnellstmöglich auffallen. Und nicht erst, wenn man es braucht.

Stufe 3: Wer merkt, wenn es nicht läuft?

Ein Backup, das ohne es zu merken nicht mehr läuft ist das eigentliche Risiko. Deshalb meldet der Offsite-Dienst nach jedem Lauf das Ergebnis an einen Push-Monitor in Uptime Kuma. Eine URL mit status=up oder status=down. Bleibt es aus, weil der Container hängt oder der Server aus ist, geht er von selbst auf Rot und informiert via Slack. Gemeldet wird also diesmal nicht der Erfolg, sondern das Ausbleiben.

Die erste Stufe hängt mit dran: Bevor restic loslegt, prüft das Skript, ob in last/ ein Dump jünger als 26 Stunden liegt.

Zurückspielen

Ein Backup, das nie getestet wurde, ist kein Backup. Die Probe lief gegen einen frischen Postgres-Container; gegen die echte Instanz ist es derselbe Befehl:

bash
docker run --rm -i --network traefik-public -e PGPASSWORD="<passwort>" \
  prodrigestivill/postgres-backup-local:16 \
  sh -c 'zcat | psql -h postgres -U <benutzer> -d postgres' \
  < /mnt/ssd/backups/postgres/last/postgres-latest.sql.gz

Soll nur eine Datenbank zurückgespielt werden, kommt der Dump in einen separaten Container, und pg_dump zieht sie dann von dort heraus.

Fazit

Drei kleine Dienste, jeder mit einer Aufgabe: dumpen, wegschaffen, melden. Der Dump ist der unspektakuläre Teil. Was die Kette brauchbar macht, ist der Monitor.

Quellen

  1. prodrigestivill/docker-postgres-backup-local auf GitHub ↩

  2. restic – Dokumentation ↩

Teilen: