Protect dedicated staging disk and document verified migration

This commit is contained in:
admin committed 2026-10-27 19:38:37 +01:00
1 parent 5ab3d078fb
commit 46644e5041
7 files changed
+158 -4

No files matched your search

+65 -2
View File
@@ -31,7 +31,7 @@ Die Cloud ist immer die Quelle. Keine Uploads oder Löschungen in Nextcloud. Nur
| `~/.config/nextcloud-borg-backup/passphrase` | Bestehende Borg-Passphrase, niemals regenerieren |
| `~/.local/share/nextcloud-borg-backup/staging/` | Unverschlüsselter, privater Cloud-Zwischenstand |
| `~/.local/share/nextcloud-borg-backup/staging.owner.json` | Bindung des Zwischenstands an die Cloud-Quelle |
| `~/.local/state/nextcloud-borg-backup/last-success.json` | Zeitpunkt, Archivname, Dateizahl und Bytezahl der bestätigten Sicherung |
| `~/.local/state/nextcloud-borg-backup/last-success.json` | Zeitpunkt, Archivname, Dateizahl, Bytezahl und tatsächlicher Staging-Pfad der bestätigten Sicherung |
| `~/.local/state/nextcloud-borg-backup/last-attempt.json` | Laufstatus und Fehlerphase |
| `~/.local/state/nextcloud-borg-backup/repository.json` | Bindung an die Borg-Repository-ID |
| `~/.local/state/nextcloud-borg-backup/verified-inventory.json` | Zuletzt geprüfte Datei-Inventur mit Größen, Zeiten und Serverhashes |
@@ -44,6 +44,7 @@ Vollständige Kindprozessausgaben stehen im systemd-Journal; die zusätzlichen A
- Ausschließlich ein Lauf dank `flock`; auch manuelle Wartungsbefehle verwenden denselben Lock. Borg besitzt zusätzlich seinen eigenen Repository-Lock. Fremde Borg-Prozesse werden nicht durch automatisches `break-lock` übergangen.
- Der NFS-Share muss exakt `EXPECTED_NAS_SOURCE` mit `EXPECTED_NAS_FSTYPE` entsprechen. Für die Workstation: `thor:/volume1/NetBackup`, `nfs4`. Autofs wird vor der Prüfung durch einen begrenzten Zugriff ausgelöst. Backup legt keine Verzeichnisse unter `/net` und kein Repository an.
- Erste Quell-Plausibilisierung gegen das jüngste vorhandene Borg-Archiv; danach gegen den letzten bestätigten Stand. Rückgang von Dateizahl **oder** Bytezahl um mehr als `MAX_SOURCE_DROP_PERCENT=20` führt zum Abbruch vor der Synchronisierung. Leere Quelle wird immer abgewiesen.
- Bei konfiguriertem `EXPECTED_STAGE_MOUNT`/`EXPECTED_STAGE_UUID` werden der exakte lokale Mount und seine UUID vor der Anlage des Zwischenstands geprüft; ein fehlender oder fremder Datenträger führt zum Abbruch. Beide Werte müssen zusammen gesetzt werden.
- Staging muss lokal sein, darf keine Symlinks/Mounts enthalten und darf sich nicht mit State, Repository oder `~/Nextcloud` überschneiden. Ein bereits gefülltes, fremdes Verzeichnis wird nicht übernommen.
- Hashvergleich, wenn jede Quelldatei MD5/SHA1 anbietet. Dateien ohne Serverhash werden vor dem Sync mit `rclone copy --ignore-times` erneut gelesen und anschließend zusätzlich per `rclone check --download` verglichen. Leere Dateien sind bereits durch Größe null eindeutig. Bei Zeilenumbrüchen in ungehashten Dateinamen erfolgt ein vollständiger Bytevergleich aller Dateien, weil rclones Dateiliste solche Namen nicht darstellen kann. Das kostet zusätzlich Übertragungszeit, vermeidet aber den unsicheren Rückfall auf reine Größenvergleiche.
- Zusätzlich berechnet Python die lokalen SHA1-/MD5-Werte unabhängig von rclone und vergleicht jede verfügbare Cloud-Prüfsumme sowie die Dateigrößen.
@@ -106,7 +107,7 @@ Passphrase und exportierten Schlüssel unabhängig vom NAS und der Workstation s
`make check` prüft Bash-Syntax, Python, alle vier systemd-Units und automatisierte Ausfallszenarien. Integrationstests verwenden echtes rclone mit lokalem Test-Remote sowie echtes Borg in temporären Verzeichnissen: Archiv erstellen, Daten prüfen, extrahieren und Bytevergleich. Sie verändern weder echte Cloud noch produktives Repository.
18 Tests prüfen außerdem leere/geschrumpfte Quelle, falsches NAS, fremdes/symlinkendes Staging, Netzfehler in Sync und Check, geänderte Cloud-Inventur, Repository-Austausch, konkurrierende Läufe, Timeout, Zeitrücksprung und Wartungswiederholung. Gleiche Dateigröße und gleicher Zeitstempel bei geändertem Inhalt werden im Integrationstest ausdrücklich abgedeckt.
21 Tests prüfen außerdem leere/geschrumpfte Quelle, falsches NAS, fremdes/symlinkendes Staging, Netzfehler in Sync und Check, geänderte Cloud-Inventur, Repository-Austausch, konkurrierende Läufe, Timeout, Zeitrücksprung und Wartungswiederholung. Gleiche Dateigröße und gleicher Zeitstempel bei geändertem Inhalt werden im Integrationstest ausdrücklich abgedeckt.
Der Installer erhält private Konfiguration und Schlüssel, hält vorhandenen Backup-Dienst und Timer gemeinsam an, ersetzt Programme und Units atomar und startet die Timer neu. Der Update-Test prüft die Erhaltung von Konfiguration und Schlüssel sowie den Timer-Stopp. Eine fehlende Passphrase bei vorhandenem Repository führt zum Abbruch. Die Deinstallation stoppt Backup/Timer und entfernt Programme/Units; Daten, Schlüssel, State und Archive bleiben erhalten.
@@ -151,3 +152,65 @@ Der vollständige Lauf am 26.10.2026 dauerte von 12:26:38 bis 13:01:15 Uhr MEZ u
Die Wiederherstellungsprobe ist eine Stichprobe von drei Dateien; die Borg-Datenprüfung erfasst den vollständigen neuen Archivstand. Die extrahierten Proben und deren Hash-Nachweis liegen privat unter `~/.local/state/nextcloud-borg-backup/restore-proof-20261026/` bzw. `restore-proof.json`. Dateinamen und private Inhalte wurden nicht in Git übernommen.
Nach dieser Abnahme wurde der endgültige Installer nochmals produktiv ausgeführt. Konfiguration und Passphrase blieben erhalten, installierte Programme entsprechen dem Repository. Die eigene rclone-Konfiguration wurde auf Dateirechte 0600 beschränkt. Der Zwischenstand belegt etwa 36 GiB; anschließend waren auf dem Home-Dateisystem noch etwa 124 GiB frei.
## Zwischenstand auf der Datenplatte ab 27.10.2026
Die Workstation verwendet nun den tatsächlichen Pfad
`/mnt/data/johannes/nextcloud-borg-backup/staging`. Der bisherige Home-Pfad
`~/.local/share/nextcloud-borg-backup/staging` und der zusätzliche sichtbare
Zugang `~/Nextcloud-Zwischenstand` sind Symlinks für den manuellen Zugriff.
Auch `staging.owner.json` ist vom bisherigen Home-Ort auf die tatsächliche
Owner-Datei auf der Datenplatte verlinkt. Im Backup ist ausschließlich der echte
Pfad konfiguriert; die bestehende Ablehnung symlinkender Staging-Pfade bleibt aktiv.
`EXPECTED_STAGE_MOUNT=/mnt/data` und die fest eingetragene UUID der Datenplatte
werden vor dem Anlegen des Zwischenstands und vor dem Sync geprüft. Fehlt die
Platte oder liegt ein fremdes Dateisystem unter `/mnt/data`, bricht der Lauf ab,
statt die Systemplatte mit einem neu angelegten Zwischenstand zu belegen.
Die UUID wird nicht bei jedem Lauf dynamisch neu übernommen. Die Konfiguration
ist privat; auf anderen Rechnern den tatsächlichen Mount und dessen UUID bewusst
hinterlegen oder beide optionalen Schutzwerte leer lassen.
Der Umzug wurde bei angehaltenen Timern und mit Backup-Lock durchgeführt.
8.218 Dateien mit exakt 38.274.641.627 Bytes wurden kopiert, Quelldateien mit
SHA-256 geprüft und neue Datenkopien unabhängig zurückgelesen. Identische Dateien
sind auf Btrfs unabhängige Reflinks. Das unveränderte Original blieb nach der
Symlink-Umschaltung zunächst erhalten. Die endgültige Freigabe zum Entfernen
dieser alten lokalen Kopie ist an eine neue vollständige Sicherung am neuen
Pfad gebunden. Schlüssel, NAS-Repository und dessen Identitätsbindung wurden
nicht verlagert.
Die Programme sind gezielt installiert, ohne den normalen Installer während der
Migration aufzurufen. Runner-Revision 4 und Wrapper entsprechen den
Repository-Dateien. `make check` besteht mit 21 Tests, einschließlich echter
lokaler rclone-/Borg-Sicherung und Restore sowie fehlendem/falschem Datenträger.
Die drei neuen Mount-Tests prüfen insbesondere, dass vor einem Fehler kein
Staging-Verzeichnis angelegt wird.
### Produktive Umzugsabnahme
Am 27.10.2026 wurde vom neuen tatsächlichen Staging-Pfad eine vollständige
Sicherung ausgeführt. Der Lauf von 18:05:41 bis 19:26:28 Uhr MEZ endete mit
Status 0 und erfolgreicher Wartung:
| Prüfung | Ergebnis |
| --- | --- |
| Neues NAS-Archiv | `nextcloud-2026-10-27_18-50-45` |
| Bestand | 8.218 Dateien, 38.274.641.627 Originalbytes |
| Cloud-Abgleich und unabhängige lokale Hashes | Erfolgreich; 230 Dateien ohne geeigneten Serverhash zusätzlich per Download verglichen |
| Wechselnde Hash-Metadaten | 29 Dateien zusätzlich inhaltlich geprüft, keine Inhaltsabweichung |
| Archiv-Datenprüfung | `borg check --archives-only --verify-data --glob-archives <neues Archiv>` erfolgreich |
| Repository und Wartung | Repository-Check, Retention und Compact erfolgreich |
| Ursprünglicher Zwischenstand | Erst nach erfolgreichem neuen Backup entfernt |
| Automatik und Zustand | Beide Timer wieder `active/waiting`, `health` meldet `healthy: true` |
Die private Ausgangskonfiguration, bisherigen Programme, Owner-Datei und
Umzugs-/Prüfberichte sind unter
`~/.local/state/archwork-storage-20261027/` gesichert. Keine dieser privaten
Dateien gehört ins Repository. Die vorherige Konfiguration darf nicht blind
zurückkopiert werden: Der alte Home-Pfad ist jetzt ein Symlink und wäre als
Backup-Arbeitsverzeichnis absichtlich unzulässig. Für einen erneuten Umzug
wieder den tatsächlichen Zielpfad konfigurieren, Owner-Datei und feste
Datenträgeridentität passend setzen und vor Entfernen der alten Daten prüfen.