# 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 (`//full/` bzw. `.../incremental//`). - `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-cli` — `full`/`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 | **bestanden** — `TestFullBackup_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 | **bestanden** — `TestVerify_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 | **bestanden** — `TestRotate_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. ## Nachtrag (BAK-03): Verify prüft jetzt auch pg_wal.tar.gz Beim Bau von BAK-03s echtem Restore-Test fiel auf, dass `pg_basebackup` (Standard-WAL-Methode `stream`) bei `-Ft -z` NEBEN `base.tar.gz` eine zweite Archivdatei `pg_wal.tar.gz` erzeugt, die `Verify` bislang nie geprüft hat — eine Sicherung mit beschädigtem WAL-Archiv wäre unbemerkt nicht crash-konsistent wiederherstellbar gewesen. `Verify` prüft seither beide Archive vollständig (siehe `BAK-03-PRUEFPROTOKOLL.md`). Das Sicherungsverfahren selbst (Format, Ort, Rotation) bleibt unverändert.