Zum Inhalt springen

Notfallwiederherstellung

Dies ist das Betriebs-Runbook zum Wiederherstellen von Orimora nach einem echten Vorfall. Es ergänzt Backup & Wiederherstellung (was gesichert wird + Zeitplan). Halte eine Kopie dieser Seite — und deinen Recovery-Code — dort bereit, wo du sie erreichst, wenn die Instanz steht.

KennzahlZielHinweise
RPO (max. akzeptabler Verlust)24 hTägliches Backup um 03:00 UTC (BACKUP_SCHEDULE).
RTO (max. akzeptable Ausfallzeit)4 hManuelle Wiederherstellung + Boot; mit diesem Runbook machbar.
  1. Den aktuellen DB-Dump (orimora-db-<ts>.dump, pg_dump-Custom-Format).
  2. Das aktuelle Uploads-Archiv (uploads-<ts>.tar.gz).
  3. Den Recovery-Code — den privaten age-Schlüssel (AGE-SECRET-KEY-…), der bei der Einrichtung einmalig unter Einstellungen → Admin → Backups angezeigt wird.

Off-Site-Artefakte heißen *.age (verschlüsselt). Lokale Kopien auf dem Host unter BACKUP_PATH sind Klartext (der Host hält ohnehin die Live-DB) — wenn das Host-Volume noch existiert, überspringe den Entschlüsselungsschritt.

Der PostgreSQL-Client muss zur Major-Version (16) des Servers passen — das Image bringt postgresql16-client mit. age und rclone sind ebenfalls im Image enthalten.

Terminal-Fenster
# 0. App stoppen, damit während der Wiederherstellung nichts schreibt.
docker compose stop app
# 1. Aktuelle Off-Site-Artefakte holen (Beispiel: rclone-Remote namens "offsite").
rclone copy offsite:orimora ./restore --include '*.age'
# 2. Mit dem Recovery-Code entschlüsseln (privater age-Schlüssel).
printf '%s\n' "$AGE_SECRET_KEY" > /tmp/orimora-recovery.key
age -d -i /tmp/orimora-recovery.key -o ./restore/db.dump ./restore/orimora-db-<ts>.dump.age
age -d -i /tmp/orimora-recovery.key -o ./restore/uploads.tar.gz ./restore/uploads-<ts>.tar.gz.age
shred -u /tmp/orimora-recovery.key # Schlüssel nicht auf der Platte lassen
# 3. Datenbank wiederherstellen (in eine saubere DB).
# Entweder bestehende DB löschen+neu anlegen, oder in eine frische restoren und DATABASE_URL umbiegen.
pg_restore --clean --if-exists --no-owner --no-privileges \
--dbname="$DATABASE_URL" ./restore/db.dump
# 4. Uploads wiederherstellen (entpackt zurück nach ./uploads/...).
tar -xzf ./restore/uploads.tar.gz -C /app # Ziel an dein Uploads-Elternverzeichnis anpassen
# 5. App starten. Der Entrypoint führt Migrationen fail-closed aus, bevor er ausliefert.
docker compose up -d app

Nach dem Boot prüfen: Login funktioniert, ein Dokument mit Anhang rendert sein Bild (Blob aufgelöst), und Einstellungen → Admin → Backups zeigt grünen Health-Status.

SzenarioWas passiert istMaßnahme
(a) Volume-/Host-VerlustServer oder Platte ist weg.Neuen Host bereitstellen, Image installieren, Off-Site-*.age ziehen, vollständigen Ablauf fahren.
(b) Korrupte DBDB unlesbar, Host intakt.Lokalen Klartext-Dump nutzen (Entschlüsselung überspringen); pg_restore --clean in dieselbe DB.
(c) Fehlerhafte MigrationEine Migration hat Schema/Daten zerlegt.Letzten Pre-Vorfall-Dump wiederherstellen, dann den korrigierten Build deployen.
(d) Ransomware / TotalverlustHost kompromittiert, lokale Backups weg.Nur aus der Off-Site-Kopie wiederherstellen. Genau dafür sind Off-Site + Verschlüsselung Pflicht.

Off-Site nutzt ein rclone-Remote (BACKUP_RCLONE_REMOTE). rclone liest seine Konfiguration aus rclone.conf oder RCLONE_CONFIG_*-Env. Bevorzuge schlüssel-/passwortbasierte Backends (kein OAuth auf einem Headless-Server). Einmal mit rclone config einrichten, dann den Remote-Pfad setzen.

# SFTP zu einer zweiten Maschine (am universellsten — jeder mit einem zweiten Linux-Rechner)
[offsite]
type = sftp
host = backup.example.com
user = orimora
key_file = /home/orimora/.ssh/id_ed25519
# → BACKUP_RCLONE_REMOTE=offsite:orimora-backups
# Backblaze B2 (günstiger Objektspeicher, S3-frei, schlüsselbasiert)
[offsite]
type = b2
account = <keyId>
key = <applicationKey>
# → BACKUP_RCLONE_REMOTE=offsite:my-orimora-bucket
# WebDAV (Nextcloud / generisch)
[offsite]
type = webdav
url = https://cloud.example.com/remote.php/dav/files/orimora/
vendor = nextcloud
user = orimora
pass = <obscured — via `rclone obscure` setzen>
# → BACKUP_RCLONE_REMOTE=offsite:orimora-backups

Führe mindestens monatlich einen vollständigen Restore-Drill durch, sowie nach jeder Änderung an der Backup-Pipeline. CI fährt bei jedem Push den Round-Trip-Restore und den Encrypt→Off-Site-Round-Trip; der monatliche Drill übt den echten, durchgängigen manuellen Ablauf gegen eine Wegwerf-Umgebung.

Checkliste:

  1. Off-Site-Artefakte vorhanden und aktuell.
  2. Mit dem Recovery-Code entschlüsseln.
  3. pg_restore in eine Wegwerf-DB.
  4. Tabellenanzahl stimmt mit der Quelle überein.
  5. Ein bekanntes Dokument und sein Anhang lösen auf.
  6. Die Wall-Clock-Zeit festhalten — sie muss ≤ RTO (4 h) liegen.