Zum Inhalt

Backup & Disaster-Recovery

Vesana hat ein eingebautes Backup-System unter Admin → System → Backup & DR. Es ist der eine Standard — kein separater Sidecar, kein manuelles pg_dump nötig.

Ein System, vier Auslöser

Alle Backups landen in EINEM Katalog, an EINEM Ort, unter EINER Aufbewahrung:

Typ Wann
Geplant Täglicher Auto-Voll-Dump (Standard an, 02:00 UTC)
Manuell Knopfdruck „Jetzt sichern"
Pre-Restore Automatisch vor jedem Restore (Reversibilität)
Pre-Update Automatisch vor jedem Online-Update durch den Updater

Das Backup ist ein vollständiger pg_dump (komprimiert, .sql.gz) inklusive der TimescaleDB-Hypertables (Check-History, Logs). Es liegt im Docker-Volume backup-data (/var/lib/vesana/backups).

FIELD_ENCRYPTION_KEY ist das Einzige, was wirklich nicht ersetzt werden kann

Verschlüsselte DB-Felder (SNMP-Communities, SNMPv3- und SSH-Passwörter) lassen sich ohne diesen Schlüssel niemals wieder entschlüsseln. Der Schlüssel muss außerhalb des Backups liegen — im Passwort-Manager + Print-Backup im Tresor. Backup-Dump und FIELD_ENCRYPTION_KEY getrennt aufbewahren.

Zeitplan & Aufbewahrung

Unter Admin → System → Backup & DR → Zeitplan & Aufbewahrung:

Einstellung Default Bedeutung
Tägliches Backup an Automatischer Voll-Dump einmal pro Tag
Uhrzeit (Stunde, UTC) 2 Stunde, ab der das Tages-Backup erzeugt wird
Max. Anzahl 5 mehr Backups → älteste fliegen
Max. Alter (Tage) 90 ältere werden gelöscht
Max. Disk (GB) 10 Gesamt-Cap; ältere fliegen bis darunter

Das strengste der drei Retention-Limits gewinnt. Pre-Update- und Pre-Restore-Backups zählen mit. Ein Watcher prüft stündlich, ob das Tages-Backup fällig ist, und ein Cleanup-Job räumt alle 6 h gemäß den Limits auf.

Off-Site-Kopie (wichtig)

Backups liegen lokal auf diesem Server. Bei einem Totalausfall der Maschine sind sie mit weg. Für echte Disaster-Recovery brauchst du eine Off-Site-Kopie:

  • In der UI „Herunterladen" auf einem Backup → speichert die .sql.gz lokal.
  • Oder per eigenem Script aus dem Volume wegkopieren:
docker run --rm -v vesana_backup-data:/src -v $(pwd):/dst alpine \
  sh -c 'cp /src/*.sql.gz /dst/'
# danach nach S3 / NAS / USB rotieren

Restore (auf laufendem Server)

In der UI: bei einem Backup auf „Restore" → Hostname tippen (Type-To-Confirm) → 2FA bestätigen (Single-Use-Token) → einspielen.

Der Restore ist TimescaleDB-sicher: er fährt timescaledb_pre_restore() / timescaledb_post_restore() um den Dump und terminiert offene DB-Sessions, damit die Hypertable-Chunks korrekt zurückkommen. Vorher wird automatisch ein Pre-Restore-Backup des aktuellen Standes angelegt.

Restore = Wartungsfenster

Der Restore überschreibt die Datenbank und trennt laufende Sessions. Alle Änderungen seit dem gewählten Backup gehen verloren. Nicht während des Betriebs leichtfertig auslösen.

Disaster-Recovery: frischer Server

Ziel: Server crasht → frischer Server → Backup von gestern rein → Stand von gestern zurück, nichts verloren außer dem laufenden Tag.

  1. Neuen Server mit setup.sh aufsetzen (wie bei einer Erstinstallation). Beim ersten Start laufen die Migrationen → leeres Schema + TimescaleDB-Extension sind da.
  2. FIELD_ENCRYPTION_KEY aus dem alten .env übernehmen (sonst sind verschlüsselte Felder nach dem Restore unlesbar). Ebenso SECRET_KEY, wenn bestehende Logins weitergelten sollen.
  3. Als Super-Admin einloggen → Admin → System → Backup & DR.
  4. „Backup hochladen" → die .sql.gz deiner Off-Site-Kopie wählen. Sie erscheint als manuelles Backup im Katalog.
  5. Auf dem hochgeladenen Backup „Restore" → Hostname tippen → 2FA → einspielen.
  6. Verifizieren: Login mit dem Original-Admin, einen Host mit verschlüsseltem snmp_community öffnen (Wert muss intakt sein), Check-History eines Services prüfen (Hypertable-Chunks müssen da sein).

Erscheint in Schritt 6 ein verschlüsseltes Feld leer/kaputt, war der FIELD_ENCRYPTION_KEY nicht der richtige.

Disaster-Drill

Restore ohne Test ist Hoffnung, kein Backup. Empfehlung: einmal pro Quartal das Fresh-Server-Runbook auf einer separaten VM durchspielen — inklusive Schritt 6.

Anschluss