← Übersicht  ·  Skripte & Dateien  ·  cloud-host · Notfall

Disaster-Runbook

Was im Notfall zu tun ist – ohne im Notfall nachzudenken. Erst die ersten 5 Minuten, dann Schritt für Schritt je Szenario: Server kompromittiert, Daten verloren, Region-Ausfall, DNS-Problem, Secrets geleakt, Ransomware. Am Ende der komplette Wiederaufbau von Null und eine Checkliste zum Ausdrucken.

Stand: 30. August 2026 bindet Snapshot + Backup + DNS (Domain Name System) + Secrets zusammen vorher lesen, nicht im Ernstfall

Platzhalter einsetzen – nur im Browser

Erste 5 Minuten

Nicht sofort etwas löschen oder neu bauen. Erst verstehen, dann handeln.

Nicht erfunden: jede Meldung hier ist in dieser Sammlung mindestens einmal tatsächlich aufgetreten.

Zeichnung aus Diagramme: Hetzner & CRC (37).

Der Aufruf kommt zurück – aber falsch 401 / 403 issuer-uri gegen den iss-Claim im Token vergleichen http gegen https – zeichengenau. Zeichnung 14 und 31. Sonst: Uhr des Servers prüfen – ein abgelaufenes exp sieht genauso aus wie ein falscher Schlüssel. 404 Route vorhanden? Zeigt sie auf den richtigen Service? oc get route · der Hostname muss exakt stimmen 503 zwei Ursachen Kein bereiter Pod im Endpoint oc get endpoints – leer? Dann Readiness prüfen. Zeichnung 23. Circuit Breaker offen – obwohl der Dienst läuft Actuator-Endpunkt abfragen. Zeichnung 15: 422 als Fehler gezaehlt. Der Unterschied ist entscheidend Oben ist die Infrastruktur schuld, unten der Anwendungscode. Beide melden dasselbe. Wer nur die Route und die Pods ansieht, sucht im zweiten Fall stundenlang am falschen Ende. 504 Der Dienst antwortet, nur zu langsam Last ansehen, dann den Verbindungspool – nicht die Route Der Pod kommt nicht hoch Pending Der Scheduler findet keinen Platz oc describe node – Taints wie DiskPressure? PVC ungebunden? ImagePullBackOff Name, Tag oder Zugangsdaten Innen die svc-Adresse, außen die Route – Zeichnung 09 und 19 CrashLoopBackOff Erst die Logs des vorigen Laufs lesen oc logs --previous · sonst: livenessProbe zu knapp? Running, aber 0/1 Läuft, ist aber nicht bereit – kein Verkehr Der häufigste Fall hinter einem 503. Zeichnung 23. Die Reihenfolge, die am schnellsten zum Ziel führt 1 · oc get pods – Spalte READY, nicht STATUS 2 · oc describe pod – die Events ganz unten 3 · oc logs --previous – der Lauf, der gescheitert ist 4 · oc get endpoints – steht der Pod überhaupt drin? Erst wenn oc selbst in Zeitüberschreitungen läuft, ist die Control Plane das Problem – dann crictl auf dem Node. Die Events aus Schritt 2 sind fast immer schon die Antwort. Beim Bauen und Schieben manifest unknown Bitnami-Paywall – auf bitnamilegacy umbiegen short-name did not resolve Podman will den vollen Namen – Zeichnung 20 alte Fassung läuft weiter Derselbe Tag neu geschoben – der Tag muss sich ändern Was fast immer stimmt Die Meldung nennt das Symptom, nicht die Ursache. 503 zeigt auf die Infrastruktur, obwohl zweimal der Code schuld war. Deshalb lohnt die Frage vor jeder Suche: Was hat sich zuletzt geändert? – das schlägt jede Systematik.
Vom Symptom zur Stelle, an der man nachsieht. Die drei Bänder sind nach dem sortiert, was man zuerst sieht: eine HTTP-Antwort, ein Pod-Zustand, eine Meldung beim Bauen. Der wichtigste Eintrag ist der doppelte 503 – dieselbe Meldung, zwei völlig verschiedene Ursachen, und die zweite kostet Stunden, wenn man sie nicht kennt.

Triage – in dieser Reihenfolge

  1. Was ist kaputt? Eine App, der ganze Server, DNS, oder „alles langsam“? → Monitoring / ssh / hcloud server list / dig seb4u.com.
  2. Sind Daten in Gefahr? Wenn ja → zuerst ein frisches Backup bzw. einen Snapshot ziehen, bevor du irgendwas änderst.
  3. Ist es ein Angriff? Unbekannte Prozesse, ausgehender Traffic, fremde SSH-Keys? → Abschnitt 1, Server isolieren, nicht neu starten.
  4. Blutung stoppen: betroffenen Dienst stoppen (docker compose stop), Firewall auf „alles zu“, oder Server über die Hetzner-Console herunterfahren.
  5. Notieren, was du tust (Uhrzeit, Befehl). Im Stress vergisst man den eigenen letzten Schritt.
Die zwei häufigsten Fehler im Notfall

1. Den kompromittierten Server „schnell neu aufsetzen“ und dabei die Beweise + die Backups überschreiben. 2. Aus einem Snapshot wiederherstellen, der die Kompromittierung schon enthält.

1 Server kompromittiert

  1. Isolieren, nicht neu starten. Firewall so setzen, dass nichts rein und raus geht außer deiner IP (Internet Protocol) auf SSH (Secure Shell) – oder den Server pausieren (Hetzner-Console, „Power off“). Kein Reboot: RAM-Beweise gehen verloren, und viele Backdoors starten beim Boot neu.
  2. Beweis sichern: Snapshot der Disk anlegen (hcloud server create-image --type snapshot app-host --description "forensik-$(date +%F)"). Diesen Snapshot nicht zum Wiederaufbau nehmen.
  3. Umfang abschätzen: last, journalctl -u ssh, ~/.ssh/authorized_keys aller Nutzer, crontab -l, systemctl list-units --type=service, ausgehende Verbindungen (ss -tunp). Ab wann? Was wurde erreicht?
  4. Neu bauen – von Grund auf, nicht aus dem Snapshot: frischer Server aus deiner cloud-init-Konfiguration, dann nur die Nutzdaten aus dem Backup zurück (Datenbank-Dumps, Upload-Ordner – keine System-Dateien, keine Binaries).
  5. Alle Secrets rotieren – siehe Abschnitt 5. Annehmen, dass alles, was auf dem Server lag, abgeflossen ist.
  6. Einfallstor schließen: war es ein schwaches Passwort, eine alte Software-Version, ein offener Port? → Server-Hardening durchgehen, bevor der neue Server ans Netz geht.

2 Daten verloren / kaputt

Versehentliches DROP TABLE, kaputte Migration, rm -rf, stille Dateibeschädigung.

  1. Schreibzugriff stoppen, damit nichts weiter überschrieben wird: Dienst / Datenbank-Container stoppen.
  2. Was ist der letzte gute Stand? restic snapshots zeigt die Zeitpunkte. Bei einer Fehlmigration: der Snapshot davor.
  3. Erst an einen Nebenpfad zurückholen, nicht über die Live-Daten: restic restore <id> --target /restore, dort prüfen, dann gezielt einspielen (eine Tabelle, ein Ordner).
  4. Datenbank: Dump aus dem Snapshot in eine leere DB einspielen, verifizieren, dann umschalten. Nicht in die laufende, beschädigte DB importieren.
  5. Danach: warum ist es passiert? Migration ohne Backup davor? Kein --dry-run? → Ablauf anpassen (CI/CD: Backup als Pflichtschritt vor jeder Migration).
Voraussetzung

Das funktioniert nur, wenn die Backups getestet sind. Ein nie zurückgespieltes Backup ist eine Vermutung, kein Backup.

3 Region- / Provider-Ausfall

  1. Bestätigen: status.hetzner.com. Ein einzelner Server-Ausfall ist kein Region-Ausfall – dann Abschnitt 7.
  2. Wiederaufbau in einer anderen Location: .\scripts\cloud.ps1 up -Location hel1 bzw. fsn1 / nbg1. Aus dem Off-site-Backup (Storage Box liegt in einem anderen Rechenzentrum) – ein Snapshot aus der ausgefallenen Region hilft nicht.
  3. DNS umbiegen: A-Record auf die neue IP. Wenn die Zone bei Cloudflare liegt und TTL (Time To Live) niedrig ist (300 s), greift das in Minuten.
  4. Wenn du eine feste Primary IP gebucht hattest: die ist an die Region gebunden – im Ausfall trotzdem neue IP + DNS.

Realistisch: für ein Hobby-/Projekt-Setup ist die Antwort auf einen Region-Ausfall „in einer anderen Region neu aufbauen, ~30 Min Ausfall“. Echtes Multi-Region-HA kostet dauerhaft das Mehrfache und lohnt hier nicht.

4 DNS- / Domain-Problem

SymptomUrsache & Schritt
Seite nicht erreichbar, Server läuftA/AAAA-Record falsch/fehlt, oder Cloudflare-Proxy aus. dig +short seb4u.com vs. echte IP.
„DNS_PROBE_FINISHED_NXDOMAIN“Nameserver bei der Registry falsch, oder Zone gelöscht. Beim Registrar prüfen, welche NS (Name-Server-Record) gesetzt sind.
Zertifikatsfehler nach UmzugAlter Proxy/Server antwortet noch (TTL, Cache). Warten oder alten A-Record entfernen.
Domain „expired“ / gesperrtVerlängerung fehlgeschlagen (Karte abgelaufen). Beim Registrar sofort verlängern. Die Redemption-Phase ist teuer.
E-Mail kommt nicht anMX (Mail-Exchange-Record) / SPF (Sender Policy Framework) / DKIM (DomainKeys Identified Mail) / DMARC (Domain-based Message Authentication, Reporting and Conformance). Diese Records sind getrennt vom Web – ein Server-Umzug darf sie nicht löschen.
  • Wo liegt die Zone? Muss dir klar sein bevor etwas kaputt ist – i. d. R. Cloudflare. Login-Daten dazu → Abschnitt 8.
  • TTL dauerhaft niedrig halten (300 s) für Records, die sich im Notfall ändern (A des Servers). MX/TXT (Text-Record) können höher.
  • Zone-Export (BIND-Format) regelmässig sichern – dann ist ein versehentlich gelöschter Record schnell zurück. Details: Domain zu Cloudflare.

5 Secrets geleakt

Token in Git committet, .env im Docker-Image, Server kompromittiert, Laptop verloren.

Sofort rotieren – in dieser Reihenfolge (kritisch zuerst):

Secretwo rotieren
Hetzner API-TokenCloud-Console → Security → API (Application Programming Interface) Tokens – alten löschen, neuen in hcloud context
Cloudflare API-TokenCloudflare → My Profile → API Tokens – Roll/Delete, neuen in $env:CF_API_TOKEN
SSH-Keysneues Schlüsselpaar, authorized_keys auf allen Servern ersetzen, alten Public Key bei Hetzner löschen
DB-Passwörterin der DB ändern + im Secret-Store + Dienst neu starten
App-Secrets (JWT, API-Keys Dritter)beim jeweiligen Anbieter neu erzeugen, in SOPS (Secrets OPerationS) aktualisieren
SOPS age-Schlüsselneuen erzeugen, sops updatekeys auf allen Dateien, alten Recipient entfernen
GitHub Deploy-Keys / Actions-SecretsRepo → Settings → Deploy keys / Secrets – neu setzen
Git vergisst nicht

Ein Secret aus der Git-History zu löschen (git filter-repo, force-push) ist zweitrangig – der Wert selbst muss ungültig werden. Solange du rotierst, ist der alte Wert im Verlauf harmlos.

Danach: git log -p -- pfad/zur/datei prüfen, seit wann es drin war, und ob in der Zeit etwas Verdächtiges passiert ist.

6 Ransomware

  1. Server isolieren (wie Abschnitt 1), nicht zahlen, nicht neu starten.
  2. Backups prüfen – von einem sauberen Rechner aus. Wenn die restic-Repos append-only sind (eigener Storage-Box-Sub-Account nur mit Anhänge-Recht) bzw. eine Kopie off-site liegt, kann der Angreifer sie nicht verschlüsselt haben.
  3. Neu bauen von Null (Abschnitt 7), Daten aus dem letzten sauberen restic-Snapshot – ggf. mehrere Tage zurück.
  4. Alle Secrets rotieren (Abschnitt 5).
Warum das hier meist glimpflich ausgeht

Die Verteidigung ist schon eingebaut, wenn du die anderen Anleitungen befolgt hast: getägliche verschlüsselte Backups, ein separates Off-site-Ziel, Server sind wegwerfbar. Der Hebel ist nicht „nicht infiziert werden“, sondern „in 1 h neu aufgebaut“.

7 Wiederaufbau von Null

Der Ablauf, wenn ein Server komplett weg ist. Einmal als Übung machen – dann weisst du, wie lange es dauert und was fehlt.

1Frischer Server: .\scripts\cloud.ps1 up (ggf. -Location / -Type)
2cloud-init richtet Basis + Dienste ein (aus dem Git-Repo) – Server-Basis
3Secrets: SOPS_AGE_KEY_FILE setzen, sops -d.env
4Daten: restic restore latest --target / für Upload-Ordner, DB-Dump einspielen
5Dienste starten: docker compose up -d / dienste-stack.ps1 up
6DNS: A-Record auf die neue IP – zuletzt, wenn alles läuft
7Verifizieren: Seite lädt, Login geht, ein Datensatz von gestern ist da, TLS (Transport Layer Security) ok, Backup läuft wieder
Laptop · die Übung (Zeit stoppen)
# separates Projekt/Location, damit nichts Echtes betroffen ist
.\scripts\cloud.ps1 up -Location hel1
ssh root@<neue-ip> 'cloud-init status --wait'
# Secrets + restic wie oben, dann:
curl -sf https://<neue-ip>/healthz && echo "OK nach $SECONDS s"
.\scripts\cloud.ps1 down          # Uebung beenden
Zielzeit

Von „Server weg“ bis „Seite läuft wieder“: unter 1 Stunde, wenn cloud-init und Backups sitzen. Dauert es länger oder hängt an einem fehlenden Zugang – genau das findet die Übung, nicht der Ernstfall.

8 Notfall-Zugänge

Wenn der Laptop das einzige Gerät mit allen Zugängen ist, ist ein verlorener Laptop selbst schon ein Disaster.

Zugangwo im Notfall
Hetzner-Konto2FA-Wiederherstellungscodes (ausgedruckt), Recovery-E-Mail-Zugang
Cloudflare-Konto (DNS!)2FA-Codes, Recovery-Key notiert
Domain-RegistrarLogin + 2FA-Codes – ohne Domain kein DNS
GitHub (cloud-init + Skripte)2FA-Codes, Repo einmal als git bundle auf der Storage Box
SOPS age-Privatschlüsselzweite Kopie außerhalb des Laptops (Passwort-Manager / verschlüsselter USB im Safe)
Storage-Box-ZugangPasswort im Passwort-Manager, SSH-Key zweitkopiert
Break-Glass

Die 2FA-Wiederherstellungscodes aller vier Konten (Hetzner, Cloudflare, Registrar, GitHub) ausgedruckt an einem physisch sicheren Ort – nicht als Datei auf dem Gerät, dessen Verlust der Notfall ist. Siehe Grundausstattung.

+ Vorbereitung (jetzt, nicht im Notfall)

Dieses Runbook funktioniert nur, wenn vorher steht:

  1. Backups laufen und sind getestet – mindestens ein echter Restore durchgespielt (Backup & Restore).
  2. cloud-init im Git-Repo baut einen Server komplett auf, ohne Handarbeit (Server-Basis).
  3. Secrets in SOPS, der age-Key zweitkopiert (Secrets).
  4. DNS-Zone bei Cloudflare, niedrige TTL auf den Server-Records, Zone exportiert.
  5. Monitoring meldet den Ausfall, bevor es ein Nutzer tut (Monitoring).
  6. 2FA-Codes ausgedruckt, dieser Runbook-Ausdruck dazu.
  7. Der Wiederaufbau wurde einmal geübt (Abschnitt 7) – halbjährlich wiederholen.

+ Checkliste zum Ausdrucken

Wenn etwas kaputt ist:

  1. ☐  Was genau ist kaputt? (App / Server / DNS / Angriff)
  2. ☐  Sind Daten in Gefahr? → zuerst frisches Backup / Snapshot
  3. ☐  Angriffsverdacht? → isolieren (Firewall zu / Power off), nicht rebooten
  4. ☐  Blutung stoppen (Dienst stoppen)
  5. ☐  Uhrzeit + jeden Schritt mitschreiben

Wiederaufbau:

  1. ☐  .\scripts\cloud.ps1 up (ggf. andere Location)
  2. ☐  cloud-init status --wait
  3. ☐  SOPS_AGE_KEY_FILE + sops -d.env
  4. ☐  restic restore latest + DB-Dump einspielen
  5. ☐  docker compose up -d
  6. ☐  DNS A-Record → neue IP (zuletzt)
  7. ☐  Verifizieren: Seite / Login / Daten von gestern / TLS / Backup läuft
  8. ☐  Alle Secrets rotieren, wenn Angriff im Spiel war

Notfall-Zugänge liegen: _______________________________________  (ausfüllen)

⌂ Cockpit