syncova-backup/docs/recovery-runbook.md
Jerrit Fritzsche b78a6fb51c
Some checks failed
CI / Backend (Go) (push) Failing after 32s
CI / Frontend (React/TypeScript) (push) Successful in 46s
CI / Sicherheitsprüfungen (push) Successful in 28s
Dokumentation und Aenderungsliste fuer rc8
Der Abschnitt "Wohin darf zurueckgeschrieben werden?" im Runbook ist der
wichtigste Zusatz: Dass ein Ziel an ProtectSystem=strict scheitert und nicht an
den Rechten des Verzeichnisses, sieht man dem Fehler nicht an. Die Tabelle nennt
die vier Faelle samt Grund.

Die Beispiel-Einheit in der Installationsanleitung fuehrte in denselben Fehler —
sie nannte nur das Repository in ReadWritePaths. Eine Anleitung, deren
Ergebnis keine Wiederherstellung zulaesst, ist schlimmer als keine.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-18 15:55:52 +02:00

12 KiB

Wiederherstellung — Handbuch für den Ernstfall

Dieses Dokument ist für den Moment geschrieben, in dem etwas weg ist. Es beschreibt was zu tun ist, nicht wie es gebaut wurde — das steht in recovery.md und disaster-recovery.md.

Vier Lagen, von der harmlosen zur schwersten. Suchen Sie die Ihre und überspringen Sie den Rest.

Lage Abschnitt
Einzelne Dateien oder ein Ordner sind weg 1
Ein Proxmox-Gast ist weg 2
Der Control-Server samt Datenbank ist weg, das Repository steht 3
Das Repository ist beschädigt 4

0. Zuerst: nichts überstürzen

Drei Fragen, jede kostet eine Minute und kann Stunden sparen.

Gibt es einen brauchbaren Wiederherstellungspunkt?

curl -s -H "Authorization: Bearer <token>" \
  'https://<server>/api/v1/backups?classification=recoverable' | jq '.data[0]'

recoverable bedeutet: Dieses Backup wurde zurückgeschrieben und gegen das Original verglichen. verified bedeutet nur, dass die Blöcke stimmen — ein starkes Indiz, aber kein Nachweis. unverified heißt: ungeprüft.

Lässt sich der Punkt überhaupt zurückspielen?

curl -X POST https://<server>/api/v1/restores/validate \
  -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' \
  -d '{"backup_id":"<id>","target_type":"filesystem","target_path":"/pfad/zum/ziel"}'

Die Vorabprüfung schreibt nichts. Sie prüft, ob jeder benötigte Block noch da ist — ein Manifest allein belegt nur, dass jemand einmal etwas gesichert hat.

Wohin soll es? Schreiben Sie nach Möglichkeit neben das Original, nicht darüber. Ein Vergleich ist danach immer noch möglich; ein überschriebenes Original nicht mehr.


1. Dateien und Ordner

Wohin darf zurückgeschrieben werden?

Die wichtigste Frage, und sie ist nicht offensichtlich. Der Dienst läuft mit ProtectSystem=strict: Außerhalb weniger Pfade ist das Dateisystem für ihn schreibgeschützt, unabhängig von den Rechten des Verzeichnisses. Ein Ziel außerhalb endet mit mkdir: permission denied — und zwar erst nach der Vorabprüfung.

Ort Ergebnis
/srv/syncova-restore ✓ von setup.sh angelegt und eingetragen
weitere aus --wiederherstellungsziel ✓
/tmp/… ✗ landet im privaten /tmp des Dienstes und ist von außen unsichtbar
/etc, /usr, /var/lib, /root … ✗ vom Zielschutz gesperrt
alles andere ✗ schreibgeschützt durch ProtectSystem=strict

Der Ordnerbaum in der Oberfläche beantwortet das direkt: Er meldet je Verzeichnis, ob der Dienst dort schreiben darf — gemessen durch eine Probedatei, nicht aus den Rechtebits abgeleitet.

Ein weiteres Ziel nachträglich freigeben:

sudo systemctl edit syncova-api     # ReadWritePaths= ergänzen
sudo systemctl restart syncova-api

Über die Oberfläche

Wiederherstellungspunkte → Punkt wählen → Wiederherstellen.

  1. Ziel über den Ordnerbaum wählen. Beschreibbare Orte stehen oben als Vorschlag; ein Unterverzeichnis lässt sich anlegen.
  2. Umfang über den Backup-Browser wählen — das gesamte Backup, ein Ordner oder eine einzelne Datei.
  3. Vorabprüfung — sie schreibt nichts und stellt fest, ob jeder benötigte Block noch da ist.
  4. Ausführen.

Über die API

curl -X POST https://<server>/api/v1/restores \
  -H "Authorization: Bearer <token>" -H 'Content-Type: application/json' \
  -H "Idempotency-Key: $(uuidgen)" -d '{
    "backup_id": "<id>",
    "target_type": "filesystem",
    "target_path": "/srv/wiederhergestellt",
    "path_prefix": "daten/projekte"
  }'

path_prefix trifft einen Ordner oder eine einzelne Datei: Der Server vergleicht auf Gleichheit oder Präfix mit Verzeichnisgrenze — dokumente trifft dabei nicht dokumentation. Ohne ihn kommt alles zurück.

Den Inhalt eines Backups durchsehen, ohne etwas zurückzuschreiben:

curl -s -H "Authorization: Bearer <token>" \
  "https://<server>/api/v1/backups/<id>/contents?path=berichte" | jq '.data.entries'

Fortschritt:

curl -s -H "Authorization: Bearer <token>" \
  https://<server>/api/v1/restores/<id> | jq '.data | {status, files_restored, bytes_restored}'

Überschreiben

Drei Hürden, absichtlich:

  1. "overwrite_existing": true
  2. die Berechtigung restores.overwrite — sie steckt nicht in restores.execute
  3. "confirm_overwrite": "/srv/daten" — der Zielpfad wörtlich wiederholt

Ein versehentlich gesetztes Kennzeichen in einem Skript reicht damit nicht aus. Läuft der Schalter ins Leere, weil am Ziel nichts liegt, entfällt die Bestätigung — ein Ritual ohne Anlass gewöhnt das Wegklicken an.

Wenn eine Wiederherstellung abbricht

Sie wird nicht selbsttätig wiederholt. Ein zweiter Lauf in ein halb gefülltes Ziel kann Daten beschädigen, die der erste bereits am Platz hatte. Stattdessen fortsetzen:

curl -X POST https://<server>/api/v1/restores/<id>/resume -H "Authorization: Bearer <token>"

Die Fortsetzung räumt zuerst die beim Abbruch angefangene Datei weg und beginnt beim Prüfpunkt. Der Prüfpunkt entsteht erst, nachdem eine Datei vollständig und umbenannt am Platz liegt.

Ohne Control-Server

Geht der Server nicht, aber das Repository steht:

./bin/syncova-repo list --path /srv/syncova-repository
./bin/syncova-agent restore \
  --repository /srv/syncova-repository \
  --backup <backup-id> \
  --target /srv/wiederhergestellt

Dafür wird SYNCOVA_ENCRYPTION_KEYS gebraucht — bei einem verschlüsselten Repository liegt der Datenschlüssel unter metadata/data-key.json und ist mit diesem Schlüssel versiegelt.


2. Ein Proxmox-Gast

Ungeprüft auf echter Hardware. Der Weg läuft gegen einen Nachbau der API vollständig durch, aber ob eine wiederhergestellte Maschine startet, ist nicht nachgewiesen (siehe proxmox.md). Rechnen Sie im Ernstfall mit Nacharbeit.

./bin/syncova-proxmox restore-guest \
  --cluster <verbund-id> \
  --repository /srv/syncova-repository \
  --backup <backup-id> \
  --target-guest qemu/900 \
  --node pve-01

--target-guest setzen. Ohne ihn wird der Ursprungsgast überschrieben — und wenn der noch läuft und nur Daten fehlen, vernichtet das genau den Stand, den man retten wollte.

Der Ablauf: Archiv aus dem Repository lesen (entschlüsseln, entpacken, jeder Block gegen seine Kennung geprüft) → über den Zugriffsweg auf einen Proxmox-Speicher schreiben → qmrestore anstoßen → Archiv wieder abräumen.

Danach:

  • Der Gast startet nicht von selbst. --start ist der ausdrückliche Weg. Eine wiederhergestellte Maschine, die sich mit derselben Adresse ins Netz meldet wie das noch laufende Original, richtet mehr Schaden an als der Ausfall.
  • Die Plattenzuordnung wird nicht aus der gesicherten Konfiguration gesetzt. Sie verwiese auf den alten Ort. Das erscheint als Warnung und ist von Hand zu prüfen.
  • Ausgenommene Platten (backup=0) fehlen. Die Ausgabe nennt sie.

3. Control-Server und Datenbank

Der Fall, für den syncova-dr gebaut ist. Voraussetzung: Das Repository steht, und Sie haben den Verschlüsselungsschlüssel.

Ohne SYNCOVA_ENCRYPTION_KEYS sind die abgelegten Geheimnisse verloren. Die Backups selbst bleiben lesbar, sofern der Datenschlüssel des Repositorys mit demselben Schlüssel versiegelt war — ist er das nicht, sind auch sie weg. Deshalb gehört dieser Schlüssel außerhalb der Anlage aufbewahrt.

3.1 Ansehen, was da ist

./bin/syncova-dr inspect --repo /srv/syncova-repository

Braucht keine Datenbank. Nach einem Totalverlust will man zuerst sehen, was vorhanden ist.

3.2 Schema anlegen

./bin/syncova-migrate up

3.3 Konfiguration einspielen

./bin/syncova-dr restore --repo /srv/syncova-repository --catalog

--catalog bringt zusätzlich die Wiederherstellungspunkte zurück.

Das Einspielen ist eine Transaktion. Alles oder nichts — eine halb wiederhergestellte Anlage sieht arbeitsfähig aus und scheitert beim ersten Lauf.

3.4 Was danach von Hand zu tun ist

Nichts läuft von selbst wieder an. Das ist Absicht: Ein Zeitplan, der nachts anspringt, könnte auf eine halb wiederhergestellte Anlage schreiben.

Aufträge          angehalten      → nach Prüfung einschalten
Repositories      nicht erreichbar → nach Prüfung auf aktiv setzen
Konten            deaktiviert     → Passwörter neu vergeben
Benachrichtigungen abgeschaltet   → neu einrichten
last_verified_at  leer            → Prüfung anstoßen

Im Sicherungssatz sind nicht enthalten: Passwörter, TOTP-Geheimnisse, Zugangsdaten und Konfiguration der Benachrichtigungswege (dort steht die Webhook-Adresse, und die trägt oft ein Token im Pfad), Betriebstokens der Agenten und der Verschlüsselungsschlüssel selbst.

./bin/syncova-admin create-admin --username admin

3.5 Vor dem ersten neuen Lauf

Eine Prüfung anstoßen. Die Wiederherstellbarkeit der übernommenen Punkte ist nach dem Einspielen nicht belegt — sie wurde nicht neu nachgewiesen, und last_verified_at ist deshalb leer.


4. Beschädigtes Repository

4.1 Feststellen, was betroffen ist

./bin/syncova-repo scan --path /srv/syncova-repository --deep

Der vollständige Lauf liest jeden Block und prüft ihn gegen seine Prüfsumme. Er braucht keinen Schlüssel: Geprüft wird gegen die Prüfsumme der abgelegten Form.

Der Bericht nennt betroffene Backups namentlich. Ein Backup mit einem einzigen beschädigten Block ist nicht zu 70 % wiederherstellbar, sondern gar nicht — die Einstufung geht deshalb auf 0 %.

4.2 Katalog verloren

./bin/syncova-repo rebuild --path /srv/syncova-repository

Der Katalog ist nur ein Beschleuniger; verbindlich sind die Manifeste. Er wird bei Verlust, Beschädigung oder fremder Repository-Kennung ohnehin still neu gebaut.

4.3 Einzelnes Manifest beschädigt

Betroffen ist genau dieses eine Backup. Die Prüfung meldet es, die Wiederherstellung bricht ab (0 Dateien im Ziel, kein halbes Ergebnis), und der Katalog-Neuaufbau schließt es aus.

Dass der Katalog es zunächst weiter anzeigt, ist richtig — er ist ein Beschleuniger, nicht die Wahrheit.

4.4 Blöcke fehlen

Fehlende Blöcke lassen sich nicht wiederherstellen; sie sind weg. Was bleibt:

  1. Ein anderer Wiederherstellungspunkt derselben Kette. Da Syncova-Manifeste vollständig sind, ist jeder Punkt für sich wiederherstellbar — eine zerrissene Kette gibt es nicht.
  2. Ein exportierter Container (syncova-repo export), sofern vorhanden.

4.5 Verweigerte Löschung im gehärteten Modus

Kein Fehler, sondern der Schutz. Zum Entfernen eines geschützten Backups:

curl -X DELETE https://<server>/api/v1/backups/<id> -H "Authorization: Bearer <token>"

Der Server prüft Aufbewahrungsfrist und Legal Hold. Eine abgewehrte Löschung wird protokolliert wie eine erfolgreiche — wer wiederholt gegen den Schutz läuft, tut entweder etwas Falsches oder etwas Böses.

Eine rekursive Aufhebungsfunktion für den gesamten Schutz gibt es ausdrücklich nicht.


Wie oft man das üben sollte

Einmal im Quartal, mit einem echten Ziel und einer Stoppuhr. Die gemessene Dauer ist die einzige RTO-Angabe, die in einem Bericht etwas wert ist — alles andere ist eine Hochrechnung aus Datenmenge und Durchsatz, auf die sich im Ernstfall niemand verlassen kann.

Solange nicht gemessen wurde, steht in der RTO-Spalte der Berichte „nicht gemessen". Das ist die richtige Angabe, aber keine gute.