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
88 lines
4.8 KiB
Markdown
88 lines
4.8 KiB
Markdown
# 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-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.
|