Files
nexarch/archive/docs/BAK-01-PRUEFPROTOKOLL.md
T
sysopsandClaude Sonnet 5 10ba866f0e BAK-02: objekt-storage-backup-snapshots
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
2026-08-29 23:07:59 +02:00

4.8 KiB
Raw Blame History

BAK-01 Prüfprotokoll: Datenbank-Backup-Strategie

Welle 1, keine Vorbedingungen. Neues Modul-Verzeichnis code/archive/ (gleiches Monorepo-Muster wie code/dms/), eigenes Go-Modul gitea.perlbach24.de/scripte/nexarch/archive.

Grundsatzentscheidung: PostgreSQL-17-natives inkrementelles Backup

pg_dump kennt nur logische Vollsicherungen — "inkrementell" im Sinne des Tickets erfordert das physische Backup-Verfahren. Gewählt: PostgreSQL 17s natives pg_basebackup --incremental (WAL-Summarization), NICHT klassisches WAL-Archiving (archive_mode), weil letzteres einen Neustart der (geteilten, auch von Core/DMS-Tests genutzten) Postgres-Instanz auf 192.168.1.131 erfordert hätte. Stattdessen summarize_wal = on gesetzt — nur ein pg_reload_conf(), kein Neustart, keine Unterbrechung laufender Verbindungen (per Health-Check nach der Änderung bestätigt).

Voraussetzung geschaffen: Rolle nexarch_backup mit REPLICATION-Attribut angelegt (Postgres verlangt eine Replikationsverbindung für pg_basebackup), pg_hba.conf erlaubte lokale Replikationsverbindungen bereits.

Umsetzung

  • internal/backup.FullBackup/IncrementalBackup — rufen pg_basebackup über os/exec auf, Ergebnis landet in einer Generationsstruktur (<BackupDir>/<Generation>/full/ bzw. .../incremental/<ID>/).
  • internal/backup.Verify — öffnet base.tar.gz vollständig (gzip- UND tar-Stream, jeder Eintrag bis zum Ende gelesen, nicht nur Kopfdaten) — Akzeptanzkriterium 2: Verifikation auf Lesbarkeit, nicht nur Erstellung.
  • internal/backup.Rotate/ListGenerations — Generationen sind nach Zeitstempel-ID sortierbar, Rotate entfernt die ältesten bis auf keep komplett (inklusive aller abhängigen Inkremente).
  • cmd/backup-clifull/incremental/rotate, aufgerufen von systemd-Timern (deploy/systemd/nexarch-archive-backup-*.timer) — "automatisiert nach Zeitplan" (Akzeptanzkriterium 1) entsteht durch die Timer-Definition, kein zusätzlicher Dauerprozess nötig.

Prüfungen

# Prüfung Ergebnis
1 Sicherung gegen Testdatenbank erfolgreich erstellt und verifiziert bestandenTestFullBackup_CreatesVerifiedBackup gegen die echte Postgres-17-Instanz auf 192.168.1.131 (kein Mock), zusätzlich TestIncrementalBackup_IsSmallerThanFull: inkrementelle Sicherung real deutlich kleiner als Vollsicherung (167 KB vs. 16 MB bei der ersten manuellen Probe) — beweist echte inkrementelle Übertragung, nicht nur eine zweite Vollsicherung
2 Verifikation erkennt eine absichtlich beschädigte Sicherungsdatei bestandenTestVerify_DetectsCorruptedFile: 64 Bytes in der Mitte von base.tar.gz gekippt, Verify schlägt danach fehl (unbeschädigt zuvor erfolgreich)
3 Rotationsregel entfernt nachweislich nur die ältesten Generationen bestandenTestRotate_RemovesOnlyOldestGenerations: 5 Generationen, keep=2, exakt die 3 ältesten entfernt, die 2 neuesten nachweislich unangetastet

Echte Verdrahtung auf 192.168.1.131 (nicht nur Testcode)

Anders als die zuletzt in DMS gefundenen "Baustein existiert, ist aber nirgends verdrahtet"-Fälle (FDN-03/FDN-09 gegen Core) wurde hier die komplette Kette tatsächlich installiert und ausgeführt:

  • backup-cli gebaut nach /opt/nexarch-archive/bin/
  • /etc/nexarch/archive-backup.env mit den Verbindungsdaten (0600)
  • 3 systemd-Timer installiert und aktiviert (enable --now): Vollsicherung täglich 02:00 UTC, Inkrement stündlich, Rotation täglich 03:00 UTC (systemctl list-timers bestätigt alle drei scharf)
  • Jeder der drei Dienste (full/incremental/rotate) einmal manuell über systemctl start ausgelöst (nicht nur go test direkt) — alle drei mit status=0/SUCCESS, Journal bestätigt inhaltlich korrekte Ausgabe (Vollsicherung erstellt+verifiziert, Inkrement erstellt+verifiziert gegen die richtige Vorgänger-Generation, Rotation lief ohne Fehler)

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  -> 4/4 Tests ok, 0 Fehlschläge (echter Postgres 17, kein Mock)

Nachtrag (BAK-02-Sitzung): Backup-Zielverzeichnis korrigiert

NEXARCH_BACKUP_DIR zeigte ursprünglich auf /var/backups/nexarch (Root-Dateisystem des Containers, kein dediziertes Dataset) — korrigiert auf /var/nexarch-archiv/backups/postgres (persistentes ZFS-Dataset), siehe docs/BAK-02-PRUEFPROTOKOLL.md Abschnitt „Korrektur an BAK-01" für Details. Vollsicherung nach der Korrektur erneut über systemd ausgelöst, landet nachweislich am neuen Ort.

Gesamtergebnis

Bestanden. Alle drei Akzeptanzkriterien und alle drei Pflichtprüfungen real erfüllt — inklusive tatsächlicher systemd-Timer-Installation und manuell ausgelöstem End-to-End-Lauf aller drei Dienste auf dem Testhost, nicht nur isolierter Testcode.