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).
Triage – in dieser Reihenfolge
- Was ist kaputt? Eine App, der ganze Server, DNS, oder „alles
langsam“? → Monitoring
/
ssh/hcloud server list/dig seb4u.com. - Sind Daten in Gefahr? Wenn ja → zuerst ein frisches Backup bzw. einen Snapshot ziehen, bevor du irgendwas änderst.
- Ist es ein Angriff? Unbekannte Prozesse, ausgehender Traffic, fremde SSH-Keys? → Abschnitt 1, Server isolieren, nicht neu starten.
- Blutung stoppen: betroffenen Dienst stoppen
(
docker compose stop), Firewall auf „alles zu“, oder Server über die Hetzner-Console herunterfahren. - Notieren, was du tust (Uhrzeit, Befehl). Im Stress vergisst man den eigenen letzten Schritt.
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
- 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.
- Beweis sichern: Snapshot der Disk anlegen
(
hcloud server create-image --type snapshot app-host --description "forensik-$(date +%F)"). Diesen Snapshot nicht zum Wiederaufbau nehmen. - Umfang abschätzen:
last,journalctl -u ssh,~/.ssh/authorized_keysaller Nutzer,crontab -l,systemctl list-units --type=service, ausgehende Verbindungen (ss -tunp). Ab wann? Was wurde erreicht? - 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).
- Alle Secrets rotieren – siehe Abschnitt 5. Annehmen, dass alles, was auf dem Server lag, abgeflossen ist.
- 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.
- Schreibzugriff stoppen, damit nichts weiter überschrieben wird: Dienst / Datenbank-Container stoppen.
- Was ist der letzte gute Stand?
restic snapshotszeigt die Zeitpunkte. Bei einer Fehlmigration: der Snapshot davor. - 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). - Datenbank: Dump aus dem Snapshot in eine leere DB einspielen, verifizieren, dann umschalten. Nicht in die laufende, beschädigte DB importieren.
- Danach: warum ist es passiert? Migration ohne Backup davor? Kein
--dry-run? → Ablauf anpassen (CI/CD: Backup als Pflichtschritt vor jeder Migration).
Das funktioniert nur, wenn die Backups getestet sind. Ein nie zurückgespieltes Backup ist eine Vermutung, kein Backup.
3 Region- / Provider-Ausfall
- Bestätigen: status.hetzner.com. Ein einzelner Server-Ausfall ist kein Region-Ausfall – dann Abschnitt 7.
- Wiederaufbau in einer anderen Location:
.\scripts\cloud.ps1 up -Location hel1bzw.fsn1/nbg1. Aus dem Off-site-Backup (Storage Box liegt in einem anderen Rechenzentrum) – ein Snapshot aus der ausgefallenen Region hilft nicht. - 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.
- 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
| Symptom | Ursache & Schritt |
|---|---|
| Seite nicht erreichbar, Server läuft | A/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 Umzug | Alter Proxy/Server antwortet noch (TTL, Cache). Warten oder alten A-Record entfernen. |
| Domain „expired“ / gesperrt | Verlängerung fehlgeschlagen (Karte abgelaufen). Beim Registrar sofort verlängern. Die Redemption-Phase ist teuer. |
| E-Mail kommt nicht an | MX (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):
| Secret | wo rotieren |
|---|---|
| Hetzner API-Token | Cloud-Console → Security → API (Application Programming Interface) Tokens – alten löschen, neuen in hcloud context |
| Cloudflare API-Token | Cloudflare → My Profile → API Tokens – Roll/Delete, neuen in $env:CF_API_TOKEN |
| SSH-Keys | neues Schlüsselpaar, authorized_keys auf allen Servern ersetzen, alten Public Key bei Hetzner löschen |
| DB-Passwörter | in 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üssel | neuen erzeugen, sops updatekeys auf allen Dateien, alten Recipient entfernen |
| GitHub Deploy-Keys / Actions-Secrets | Repo → Settings → Deploy keys / Secrets – neu setzen |
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
- Server isolieren (wie Abschnitt 1), nicht zahlen, nicht neu starten.
- 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.
- Neu bauen von Null (Abschnitt 7), Daten aus dem letzten sauberen restic-Snapshot – ggf. mehrere Tage zurück.
- Alle Secrets rotieren (Abschnitt 5).
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.
.\scripts\cloud.ps1 up (ggf. -Location / -Type)SOPS_AGE_KEY_FILE setzen, sops -d → .envrestic restore latest --target / für Upload-Ordner, DB-Dump einspielendocker compose up -d / dienste-stack.ps1 up# 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
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.
| Zugang | wo im Notfall |
|---|---|
| Hetzner-Konto | 2FA-Wiederherstellungscodes (ausgedruckt), Recovery-E-Mail-Zugang |
| Cloudflare-Konto (DNS!) | 2FA-Codes, Recovery-Key notiert |
| Domain-Registrar | Login + 2FA-Codes – ohne Domain kein DNS |
| GitHub (cloud-init + Skripte) | 2FA-Codes, Repo einmal als git bundle auf der Storage Box |
| SOPS age-Privatschlüssel | zweite Kopie außerhalb des Laptops (Passwort-Manager / verschlüsselter USB im Safe) |
| Storage-Box-Zugang | Passwort im Passwort-Manager, SSH-Key zweitkopiert |
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:
- Backups laufen und sind getestet – mindestens ein echter Restore durchgespielt (Backup & Restore).
- cloud-init im Git-Repo baut einen Server komplett auf, ohne Handarbeit (Server-Basis).
- Secrets in SOPS, der age-Key zweitkopiert (Secrets).
- DNS-Zone bei Cloudflare, niedrige TTL auf den Server-Records, Zone exportiert.
- Monitoring meldet den Ausfall, bevor es ein Nutzer tut (Monitoring).
- 2FA-Codes ausgedruckt, dieser Runbook-Ausdruck dazu.
- Der Wiederaufbau wurde einmal geübt (Abschnitt 7) – halbjährlich wiederholen.
+ Checkliste zum Ausdrucken
Wenn etwas kaputt ist:
- ☐ Was genau ist kaputt? (App / Server / DNS / Angriff)
- ☐ Sind Daten in Gefahr? → zuerst frisches Backup / Snapshot
- ☐ Angriffsverdacht? → isolieren (Firewall zu / Power off), nicht rebooten
- ☐ Blutung stoppen (Dienst stoppen)
- ☐ Uhrzeit + jeden Schritt mitschreiben
Wiederaufbau:
- ☐
.\scripts\cloud.ps1 up(ggf. andere Location) - ☐
cloud-init status --wait - ☐
SOPS_AGE_KEY_FILE+sops -d→.env - ☐
restic restore latest+ DB-Dump einspielen - ☐
docker compose up -d - ☐ DNS A-Record → neue IP (zuletzt)
- ☐ Verifizieren: Seite / Login / Daten von gestern / TLS / Backup läuft
- ☐ Alle Secrets rotieren, wenn Angriff im Spiel war
Notfall-Zugänge liegen: _______________________________________ (ausfüllen)