docs(PROJ-66): Backup & Restore Runbook schreiben
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.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# PROJ-66: Backup-Strategie für archivmail (Produktiv + Teilproduktiv)
|
||||
|
||||
**Status:** In Review (BUG-1/BUG-2 aus QA-Runde 1 gefixt, Re-Test steht aus)
|
||||
**Status:** Deployed (nur CLI-Kommandos `backup`/`restore` auf 192.168.1.131 — Cron-Aktivierung, Alerting, Bitwarden-Escrow und PBS-Restore-Verifikation bleiben offen, siehe "## Deployment")
|
||||
**Erstellt:** 2026-07-04
|
||||
|
||||
## Problem / Ausgangslage
|
||||
@@ -392,6 +392,10 @@ Anforderungen:
|
||||
8. Ein Backup-Runbook (analog `docs/MIGRATION_RUNBOOK.md`) existiert unter
|
||||
`docs/BACKUP_RESTORE_RUNBOOK.md` mit Schritt-für-Schritt-Anleitung für
|
||||
Backup, Restore und Verifikation.
|
||||
**✓ Erfüllt (2026-07-05)** — `docs/BACKUP_RESTORE_RUNBOOK.md` angelegt,
|
||||
deckt App-Backup (`archivmail backup`/`restore`) und Infrastruktur-Ebene
|
||||
(PBS/`pct restore`) ab. AC 6 (Restore-Test) und AC 7 (Alerting) bleiben
|
||||
davon unberührt weiterhin offen.
|
||||
9. `update.sh`-Vollständigkeits-Check: Falls das Backup-Skript/der Cron-Job
|
||||
als Datei unter `deploy/` im Repo gepflegt wird, synct `update.sh` diese
|
||||
Datei nachweislich mit aus (Lehre aus PROJ-58, siehe Deploy-Vollständigkeits-
|
||||
@@ -620,3 +624,72 @@ der Fehler tritt nur bei der zweiten+ Inode-Referenz auf.
|
||||
|
||||
Re-Test von Punkt 1 (Build) und Punkt 5b (`-force` gegen befüllten Store)
|
||||
steht aus.
|
||||
|
||||
## QA Re-Test Runde 2 (2026-07-04, Testserver 132)
|
||||
|
||||
**Getestet gegen Commit 55131de (aktueller HEAD, `fix(PROJ-66): Build-Fehler
|
||||
in printHelp() + -force überschreibt keine Hardlinks`).** Nur die beiden zuvor
|
||||
fehlgeschlagenen Punkte erneut geprüft (übrige Punkte waren in Runde 1 bereits
|
||||
PASS und wurden nicht wiederholt). Isolierter Build via `git archive HEAD` nach
|
||||
`/tmp/qa66-build` auf 132, Funktionstest in `/tmp/qa66-test` (synthetischer
|
||||
Store mit PROJ-65-Tenant-Hardlink, `ab/abcdef123.bin` ↔ `tenant_1/abcdef123.bin`,
|
||||
Inode-geteilt, link count 2). Deploy-Repo `/opt/archivmail/_build` NICHT
|
||||
verändert, echte Produktions-/Store-Daten und echte DB nicht berührt.
|
||||
|
||||
| # | Testpunkt | Runde 1 | Runde 2 |
|
||||
|---|-----------|---------|---------|
|
||||
| 1 | `CGO_ENABLED=0 go build -buildvcs=false ./cmd/archivmail/` | FAIL (BUG-1) | **PASS** — Build exit 0, Binary 21 MB erzeugt; `cmd_import.go:310` nutzt jetzt einfache Anführungszeichen statt Backticks |
|
||||
| 5b | `restore -force` gegen befüllten Store mit Hardlinks (Normalfall) | FAIL (BUG-2) | **PASS** — Repro (2× Restore auf dasselbe Ziel, 2. Lauf mit `-force`) läuft jetzt exit 0 durch; Hardlink erhalten (Ziel-Inode identisch für `ab/` und `tenant_1/`, link count 2), Inhalt intakt |
|
||||
|
||||
**BUG-1** verifiziert gefixt: `printHelp()`-Raw-String schließt nicht mehr
|
||||
vorzeitig, gesamtes Backend kompiliert fehlerfrei.
|
||||
|
||||
**BUG-2** verifiziert gefixt: `copyTreePreservingHardlinks()` entfernt vor
|
||||
`os.Link()` eine bereits vorhandene Zieldatei (`os.Remove`, `os.IsNotExist`
|
||||
ignoriert). Vorheriger `os.Link: file exists` tritt nicht mehr auf; `-force`
|
||||
überschreibt einen mit Tenant-Hardlinks befüllten Store verlustfrei.
|
||||
|
||||
**Gesamtergebnis Re-Test: BESTANDEN.** Beide zuvor blockierenden Bugs sind
|
||||
grün. CLI-Kommandos `backup`/`restore` funktional freigegeben. Nicht Teil
|
||||
dieses Re-Tests (unverändert offen laut Implementation Notes): Cron/Timer
|
||||
(AC 1), physische Trennung (AC 3), Backup-Verschlüsselung (AC 4),
|
||||
Restore-Verifikation via echtem `reconcile` gegen realen Bestand (AC 6),
|
||||
Alerting (AC 7), Runbook (AC 8), Bitwarden-Escrow (AC 10), PBS-Restore-Test
|
||||
(AC 11). Empfehlung an devops-deploy: 55131de deployen und Status auf
|
||||
Deployed setzen; die noch offenen ACs bleiben als Folgeschritte bestehen.
|
||||
|
||||
Testartefakte (`/tmp/qa66-build`, `/tmp/qa66-test` auf 132) nach Testende
|
||||
entfernt und Entfernung verifiziert (`ls -d /tmp/qa66*` → NONE).
|
||||
|
||||
## Deployment
|
||||
|
||||
**2026-07-04, devops-deploy, Produktivserver 192.168.1.131**
|
||||
|
||||
Deploy via `bash /opt/archivmail/update.sh` auf 131 (Commit 55131de, bereits
|
||||
auf origin/main). `update.sh` synct Backend-Binary, Frontend-Build,
|
||||
systemd-Units und `/etc/cron.d/archivmail` (Wrapper-Skripte inklusive).
|
||||
|
||||
**Smoke-Test nach Deploy (kein echter Backup/Restore-Lauf gegen
|
||||
Produktivdaten):**
|
||||
|
||||
| Prüfung | Ergebnis |
|
||||
|---|---|
|
||||
| `archivmail help` zeigt `backup`/`restore` | PASS — beide Einträge korrekt gelistet, kein Syntax-/Parse-Fehler wie in QA-Runde 1 |
|
||||
| `archivmail backup` ohne `-dest` | PASS — sauberer Fehler `backup: -dest is required`, Exit 1, kein Crash |
|
||||
| Backend-Health (`systemctl is-active archivmail`, `GET /api/health`) | PASS — `active`, HTTP 200 |
|
||||
| Frontend-Health (`systemctl is-active archivmail-web`, `GET :3000/`) | PASS — `active`, HTTP 200 |
|
||||
| `/etc/cron.d/archivmail` — PROJ-66-Backup-Zeile | PASS — Zeile bleibt auskommentiert (`# 0 3 * * * root ... archivmail backup ...`), keine aktive Backup-Cron auf 131, wie gefordert |
|
||||
|
||||
Kein `archivmail backup`/`restore` gegen echte Store-/DB-Daten auf 131
|
||||
ausgeführt — nur Hilfe-/Fehlerausgabe geprüft, da noch kein `-dest`-Ziel
|
||||
(getrenntes Mount) und kein Freigabeprozess für einen echten Lauf feststehen.
|
||||
|
||||
**Offen / Folgeschritte (nicht Teil dieses Deploys):**
|
||||
- AC 1: Cron-Zeile aktivieren, sobald `-dest`-Ziel (separates Mount) feststeht
|
||||
- AC 3: physische Trennung des Backup-Ziels
|
||||
- AC 4: Verschlüsselung des Backup-Archivs selbst
|
||||
- AC 6: Restore-Verifikation via `reconcile` gegen realen Bestand
|
||||
- AC 7: Alerting bei fehlgeschlagenem Backup-Lauf
|
||||
- AC 8: Runbook für Restore-Prozess
|
||||
- AC 10: Keyfile-Escrow in Bitwarden
|
||||
- AC 11: Restore-Test gegen echten PBS-Snapshot
|
||||
|
||||
Reference in New Issue
Block a user