restic statt Eigenbau (Content-defined Chunking fuer Dedup, verschluesseltes Repository ab Werk, geprueftes Tooling). internal/objectbackup wrapt restic init/backup/check/forget ueber os/exec, cmd/objectbackup-cli fuer systemd-Timer (stuendliche Sicherung, woechentliche Vollstaendigkeitspruefung, taegliche Rotation). Auf 192.168.1.131 real verifiziert (kein Mock): zweiter Lauf gegen unveraenderten Bestand ueberraegt nichts (files_new=0), zwei identische Dateien erzeugen nachweislich nur 1 data_blob (echter Dedup-Nachweis), absichtlich gekipptes Byte in einer Pack-Datei wird von check --read-data zuverlaessig erkannt. Echt verdrahtet: 3 systemd-Timer installiert+ aktiviert, jeder Dienst einmal end-to-end via systemctl start ausgeloest. Im selben Rutsch BAK-01-Fund korrigiert: NEXARCH_BACKUP_DIR zeigte auf /var/backups/nexarch (Root-Dateisystem, kein Dataset) statt auf das persistente ZFS-Dataset /var/nexarch-archiv - korrigiert, erneut ausgeloest, landet nachweislich am richtigen Ort. objectbackup-cli-Repository liegt von Anfang an korrekt dort. Siehe archive/docs/BAK-02-PRUEFPROTOKOLL.md fuer alle Pruefungsergebnisse. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhgFcLS8tYMhDJpP74C6AQ
5.1 KiB
BAK-02 – Prüfprotokoll: Objekt-Storage-Backup/Snapshots
Welle 1, keine Vorbedingungen.
Grundsatzentscheidung: restic statt Eigenbau
Nutzerentscheidung: restic statt einer Neuimplementierung, weil restic alle
vier Akzeptanzkriterien mit ausgereiftem, breit geprüftem Tooling erfüllt
(Content-defined Chunking für Dedup, check --read-data für
Vollständigkeit, forget --keep-last für Rotation, Repository-Verschlüsselung
ab Werk). Installiert via apt-get install restic (Version 0.18.0).
Backup-Quelle ist ein lokaler Verzeichnisbaum — für den FDN-03-LocalDriver
direkt dessen Basisverzeichnis. Für S3-gestützte Produktions-Deployments
(Betriebsmodus 2/3 aus STORAGE-KONZEPT.md Abschnitt 6.2) wäre ein
vorgelagerter Sync-Schritt (z. B. rclone) nötig, um Bucket-Inhalte lokal
zu spiegeln, bevor restic sie sichert — restic sichert Dateibäume, keine
S3-Buckets direkt. Das bleibt hier bewusst unimplementiert (kein konkreter
S3-Produktionsbestand vorhanden, der das aktuell erfordert), aber
architektonisch vorgesehen und dokumentiert (README.md).
Umsetzung
internal/objectbackup.InitRepo— idempotent, erkennt "bereits initialisiert" amrestic init-Fehlertext statt zu scheitern.internal/objectbackup.Backup—restic backup --json, parst diesummary-Zeile (mehrere JSON-Zeilen in der Ausgabe, gezielt die mitmessage_type=="summary"gesucht).internal/objectbackup.Check—restic check [--read-data](Akzeptanz- kriterium 3: Vollständigkeitsprüfung).internal/objectbackup.Forget—restic forget --keep-last N --prune(Rotation).cmd/objectbackup-cli—backup <dir>/check/rotate, aufgerufen von systemd-Timern (stündlich/wöchentlich/täglich).
Prüfungen
| # | Prüfung | Ergebnis |
|---|---|---|
| 1 | Zweiter Sicherungslauf nach unverändertem Bestand überträgt keine Daten erneut | bestanden — TestBackup_UnchangedSecondRunTransmitsNothingNew: zweiter Lauf gegen unveränderten Bestand liefert files_new=0, files_changed=0, files_unmodified=1 |
| 2 | Zwei identische Testdateien belegen nachweislich nur einmal Speicherplatz | bestanden — TestBackup_DeduplicatesIdenticalContent: zwei Dateien mit identischem Inhalt erzeugen data_blobs=1, nicht 2 — echter Dedup-Nachweis über restics Content-defined Chunking, nicht nur Namensvergleich |
| 3 | Vollständigkeitsprüfung erkennt ein fehlendes Objekt in der Sicherung | bestanden — TestCheck_DetectsCorruptedPack: ein Byte in einer echten Repository-Pack-Datei gekippt, Check(readData=true) schlägt danach fehl (unbeschädigt zuvor erfolgreich) — dieselbe Vorgehensweise wie die manuelle Recherche vor der Implementierung |
Zusätzlich (nicht explizit als Pflichtprüfung gefordert, aber Teil von
Akzeptanzkriterium 3 „lässt sich einzeln prüfen"): TestForget_ KeepsOnlyRequestedSnapshotCount — 3 Sicherungsläufe, Forget(keepLast=1)
reduziert auf genau 1 verbleibenden Snapshot.
Korrektur an BAK-01 im selben Rutsch: Backup-Zielverzeichnis
Nutzerhinweis aufgegriffen: NEXARCH_BACKUP_DIR zeigte bei BAK-01
ursprünglich auf /var/backups/nexarch (Root-Dateisystem des LXC-
Containers, nicht auf einem der beiden dedizierten ZFS-Datasets). Korrigiert
auf /var/nexarch-archiv/backups/postgres (persistentes Dataset
zfs/data/subvol-1131-disk-0), NICHT /var/nexarch-test/ (ephemeres
Dataset ssd-rpool-data/swap/subvol-1131-disk-0, wird von
reset-test-env.sh-Skripten anderer Module geleert). objectbackup-clis
Repository liegt von Anfang an korrekt unter
/var/nexarch-archiv/backups/objects. Beide Pfade real auf
192.168.1.131 verifiziert (df/mount bestätigt ZFS-Dataset-Zuordnung),
BAK-01s Vollsicherung nach der Korrektur erneut über systemd ausgelöst und
bestätigt am neuen Ort gelandet.
ZFS-seitige Snapshot-/Replikations-Strategie für nexarch/archiv bleibt
bewusst außerhalb dieses Tickets (Infra-Runbook, siehe
STORAGE-KONZEPT.md Abschnitt 7 „Backup vs. Storage-Redundanz" sowie den
Hinweis, zfs dedup=on NICHT zu setzen — App-seitige Dedup über restic
genügt, ZFS-Dedup wäre auf dem 4-GB-Testhost ein Speicherrisiko).
Echte Verdrahtung auf 192.168.1.131
objectbackup-cligebaut nach/opt/nexarch-archive/bin//etc/nexarch/archive-objectbackup.env(0600)- 3 systemd-Timer installiert und aktiviert: Sicherung stündlich (
:30), Vollständigkeitsprüfung wöchentlich (So. 04:00 UTC), Rotation täglich (03:30 UTC) —systemctl list-timersbestätigt alle scharf - Jeder der drei Dienste einmal über
systemctl startausgelöst, alle mitstatus=0/SUCCESS; Journal bestätigt inhaltlich korrekte Ausgabe
Build/Test-Ergebnis (192.168.1.131, make check)
go build ./... -> clean
go vet ./... -> clean
golangci-lint run ./... -> 0 issues
go test ./... -p 1 -count=1 -> 2/2 Pakete mit Tests ok (internal/backup, internal/objectbackup), 0 Fehlschläge
Gesamtergebnis
Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real gegen echtes restic-Tooling erfüllt. BAK-01-Pfadfehler im selben Rutsch korrigiert und erneut end-to-end verifiziert.