docs/BACKUP_RESTORE_RUNBOOK.md deckt beide Sicherungsebenen ab: App-eigenes CLI-Backup (archivmail backup/restore, PROJ-66) und Infrastruktur-Ebene (PBS + Sync auf Zweitserver, pct restore). Enthaelt Bitwarden-Keyfile- Escrow-Anleitung, Pflicht-Verifikationsschritte (reconcile/reindex/ Stichprobe), Rotation-vs-DSGVO-Hinweis und den offenen Punkt "noch kein Restore-Test durchgefuehrt" als groesste verbleibende Luecke. AC 8 aus PROJ-66 damit erfuellt; AC 6 (Restore-Test) und AC 7 (Alerting) bleiben offen.
7.7 KiB
Backup & Restore Runbook – archivmail
Bezug: features/PROJ-66-backup-strategie.md (Spec + Entscheidungsverlauf),
docs/GOBD_DSGVO_CHECKLIST.md Punkt 7 (Löschsperre) und 15 (Mandantentrennung).
Ziel: belegen können, dass ein Totalausfall von Store, Keyfile oder
PostgreSQL nicht zu unwiederbringlichem Mail-Verlust führt — und dass ein
Restore im Ernstfall tatsächlich funktioniert, nicht nur theoretisch existiert.
Gilt für: archivmail backup/archivmail restore (PROJ-66, App-eigenes
CLI-Backup) und ergänzend die Proxmox Backup Server (PBS) + Sync-auf-
Zweitserver-Sicherung auf Infrastruktur-Ebene.
Grundsatz
Store, Keyfile und PostgreSQL-Metadaten sind nur gemeinsam nutzbar:
- Store ohne DB: Dateien vorhanden, aber keine Zuordnung zu Mail/Tenant.
- Keyfile ohne Store: irrelevant, nichts zu entschlüsseln.
- DB ohne Keyfile: Metadaten da, Mail-Inhalte nicht mehr lesbar (GoBD-Verstoß).
Ein Backup, das nur eine dieser drei Komponenten sichert, ist wertlos. Ein Backup, das nie zurückgespielt wurde, ist nicht verifiziert — siehe "Regelmäßiger Restore-Test" unten.
Zwei unabhängige Sicherungsebenen
- Infrastruktur-Ebene (PBS + Sync auf Zweitserver) — läuft vom
Proxmox-Host aus, sichert den kompletten Container (Store+Keyfile+
Config+PostgreSQL-Datendir+Audit-Log in einem Snapshot). Von innerhalb
des Containers nicht sichtbar/steuerbar. Siehe Memory
project_backup_infra_pbsfür CLI-Befehle (vzdump,pct restore). - App-eigenes Backup (
archivmail backup/restore) — ergänzt Ebene 1 um einen anwendungskonsistentenpg_dump(statt reinem Crash-Consistency- Snapshot) und einen selektiven, von PBS unabhängigen Restore-Weg.
Keine der beiden Ebenen ersetzt die andere. Ein vollständiger Restore-Test sollte mindestens einmal beide Wege durchlaufen haben (siehe unten).
Backup erstellen
archivmail backup --config /etc/archivmail/config.yml --dest <ziel> --keep 14
<ziel>MUSS auf einem vom Produktivsystem physisch getrennten Ziel liegen (zweiter Host, NAS, o.ä.) — siehe PROJ-66-Spec, Abschnitt "Backup-Ziel: On-Site vs. Off-Site". Ein Backup auf derselben Platte schützt nicht vor Hardware-Ausfall.- Schreibt
<ziel>/<timestamp>/:postgres.dump(pg_dump -Fc),store/(Hardlink-erhaltende Kopie, PROJ-65-Tenant-Ordner bleiben ohne Speicherplatz-Verdopplung erhalten),keyfile,config.yml,audit.log(best-effort). --keep Nbehält die letzten N Backup-Verzeichnisse, löscht ältere — nur nach erfolgreichem Lauf. Ein fehlgeschlagener Lauf lässt den partiellen Ordner stehen und rotiert nichts weg (Diagnose-Möglichkeit, kein Verlust eines guten alten Backups).- Cron-Aktivierung:
deploy/cron.d/archivmailenthält eine auskommentierte Beispielzeile. Erst aktivieren, wenn ein konkretes--dest-Ziel feststeht.
Keyfile-Escrow (Bitwarden)
Zusätzlich zum Backup: das Keyfile als unabhängige Kopie in Bitwarden hinterlegen (Secure Note, eigene Collection mit eingeschränktem Zugriff — das Keyfile entschlüsselt das gesamte Archiv aller Mandanten).
cat /etc/archivmail/keyfile
# → Wert 1:1 in eine neue Bitwarden Secure Note kopieren, Metadaten
# ergänzen (Server/Installation, Datum, wer hinterlegt hat).
Zweck: unabhängiger Wiederherstellungsweg, falls PBS/Snapshot-Infrastruktur selbst nicht verfügbar ist. Ersetzt nicht das App-Backup — beide parallel pflegen. Bei künftiger Keyfile-Rotation (aktuell nicht vorgesehen) den Bitwarden-Eintrag im selben Schritt aktualisieren.
Restore durchführen
Vorbereitung:
- Zielsystem: frischer Server/Container oder vorhandenes System im
Wartungsmodus.
archivmail/archivmail-webmüssen gestoppt sein —archivmail restorestoppt/startet die Dienste NICHT selbst. - Backup-Verzeichnis identifizieren:
<ziel>/<timestamp>/.
Durchführung:
systemctl stop archivmail archivmail-web
archivmail restore --config /etc/archivmail/config.yml \
--source <ziel>/<timestamp> [--force]
- Ohne
--force: bricht ab, wennstore_path/Keyfile bereits Inhalt haben — Schutz gegen versehentliches Überschreiben eines laufenden Systems.--forcenur auf einem bewusst freigeräumten/frischen Zielsystem nutzen. --skip-db: überspringtpg_restore, falls die Datenbank bereits separat wiederhergestellt wurde (z.B. via PBS-Snapshot der DB-Ebene).- Stellt Store (Hardlinks erhalten), Keyfile, Config und PostgreSQL
(
pg_restore --clean --if-exists) wieder her. Gibt am Ende die Pflicht-Verifikationsschritte aus (siehe unten).
Verifikation (Pflicht, nicht optional):
systemctl start archivmail archivmail-web
# Health-Check wie im Standard-Deploy-Workflow (Backend ✓, Frontend ✓)
archivmail reconcile --days 7 # PROJ-52: Zählvergleich Store vs. DB muss aufgehen
archivmail reindex # Manticore aus Store+DB neu aufbauen
# Stichprobe: 3-5 zufällige Mails über die UI öffnen und lesbar entschlüsseln
# lassen — beweist, dass Keyfile+Store+DB zueinander passen.
Restore-Ergebnis (Mail-Zahl, Zeitstempel, Dauer, welche Verifikationsschritte liefen) dokumentieren — Prinzip "Zählen, Prüfen, Belegen" wie im Migrations-Runbook.
Restore aus einem PBS-Snapshot (Infrastruktur-Ebene)
Auf dem Proxmox-Host (nicht im Container):
pct restore <neue-id> <pbs-storage>:backup/ct/<quell-id>/<timestamp> --storage <ziel-storage>
Restored als neuer Container mit <neue-id> — der Quell-Container bleibt
unangetastet. Danach dieselbe Verifikation wie oben (reconcile, reindex,
Stichprobe) im neuen Container durchführen. PostgreSQL kam dabei aus einem
Crash-Consistency-Snapshot, nicht aus einem pg_dump — WAL-Replay beim
Start ist der Normalfall, sollte aber beim Test explizit beobachtet werden
(journalctl -u postgresql auf Recovery-Meldungen prüfen).
Regelmäßiger Restore-Test
Ein Backup, das nie zurückgespielt wurde, ist nicht verifiziert. Empfehlung:
mindestens vierteljährlich einen vollständigen Restore auf einen isolierten
Test-Container durchführen (nicht auf 131/132!) — einmal über
archivmail restore (App-Backup) und mindestens einmal über pct restore
(PBS-Snapshot), jeweils mit vollständiger Verifikation. Bislang (Stand
2026-07-05) wurde noch kein Restore-Test durchgeführt — das ist die
kritischste offene Lücke in der Backup-Strategie, nicht das Fehlen eines
Backup-Ziels.
Rotation vs. DSGVO-Löschung
Backup-Rotation (--keep N, bzw. PBS-Retention) ist unabhängig von der
GoBD-Aufbewahrungsfrist der Mails selbst (PROJ-51). Eine in Produktion
bereits DSGVO-gelöschte Mail (PROJ-50) kann in einem älteren Backup noch
enthalten sein. Rotation muss kurz genug sein, dass gelöschte Daten nach
spätestens N Zyklen auch aus Backups verschwinden — Zeitraum mit
Datenschutzbeauftragtem/Nutzer abstimmen, kein rein technisches Thema.
Monitoring / Alerting (noch offen)
Größtes Risiko bei Cron-Backups: der Job schlägt still fehl, niemand merkt
es bis zum Ernstfall (Lehre aus PROJ-58: Cron-Zeilen fehlten wochenlang
trotz aktivem Code). Aktuell nicht gebaut: ein sichtbarer Alarm, wenn
das letzte erfolgreiche Backup älter als ein Schwellenwert ist. Bis dahin:
Log-Datei des Backup-Cron-Jobs (/var/log/archivmail/backup.log, sobald der
Cron aktiviert ist) manuell im Rahmen der regulären Betriebs-Checks prüfen.
Verweis
features/PROJ-66-backup-strategie.md— vollständige Spec, Optionsabwägung, QA-Ergebnisse.docs/MIGRATION_RUNBOOK.md— Vorbild für den "Zählen, Prüfen, Belegen"-Stil.- Memory
project_backup_infra_pbs— PBS/Sync-Infrastruktur-Details,vzdump/pct restore-Befehle. - Memory
project_132_teilproduktiv— 132 ist kein reiner Testserver, Backup-Sorgfalt gilt dort genauso wie auf 131.