Files
app-backup/SPEICHER.md
T

194 lines
12 KiB
Markdown

# Automatische Speicherbereinigung
## Platznot vor dem Backup: Korrektur vom 21.09.2026
Der Mailbericht vom 20.09. nennt 55.823.183.174 benötigte und
47.615.086.592 verfügbare Bytes: Es fehlen 8.208.096.582 Bytes (7,64 GiB).
Die alte Bereinigung schützt dieselben drei lokalen Kopien wie die reguläre
Retention. Dadurch kann sie bereits vor dem nächsten Backup blockieren.
`SPACE_KEEP_LOCAL=1` setzt jetzt eine eigene Untergrenze für Platznot, auch bei
bestehender Konfiguration ohne diesen Eintrag. Die neuesten so vielen gültigen,
als hochgeladen markierten lokalen Sätze bleiben erhalten. `RETENTION_KEEP_LAST=3`
gilt weiterhin für die normale Retention und wird nicht verändert. Wer die alte
Grenze ausdrücklich beibehalten möchte, setzt `SPACE_KEEP_LOCAL=3`. Null ist
unzulässig. Die Reserve `MIN_FREE_GB=10` und die Snapshot-Schätzung bleiben bestehen.
Gelöscht wird ältester Satz zuerst, nur bis der Bedarf gedeckt ist und nur nach
vollständiger lokaler Inhaltsprüfung, Remote-Datei-/Größenvergleich und bytegenauem
Vergleich von Remote-Manifest und `COMPLETE`. Für die beiden kleinen Kontrolldateien
gelten dieselben begrenzten Versuche/Zeitlimits; Archive werden nicht heruntergeladen.
Die geschützten neuesten lokalen Kopien werden zuvor ebenfalls vollständig geprüft.
Ist eine davon beschädigt oder unvollständig, bleiben alle älteren Kandidaten
erhalten; ein bloßer `UPLOADED`-Marker genügt nicht als Rückfallabsicherung.
Signalisierte Abbrüche beenden die Bereinigung, statt weitere Kandidaten zu versuchen.
Nach jeder Entfernung wird der tatsächlich freie Platz neu gemessen. Mountpoints,
auch Bind-Mounts einzelner Dateien, werden nicht rekursiv gelöscht.
Das schafft Platz, wenn ausreichend bestätigte lokale Kopien vorhanden sind.
Bei geschützten Beständen, Remote-Fehlern oder einem zu kleinen Datenträger kann
die Software keinen sicheren Platz erzwingen: Sie bricht vor dem Writer-Stopp ab
und protokolliert Bedarf, Verfügbarkeit, Defizit sowie verbleibende Archivbestände
mit belegten Bytes und Schutzgrund. Nicht bestätigte Uploads bleiben erhalten.
Das Update führt diese Bereinigung bereits vor der Installation aus; sie ist
daher auch dann wirksam, wenn der bisher installierte Stand nicht mehr starten kann.
### Wenn die geschützten Bestände den Platz belegen
`preflight.log` beziehungsweise das Backup-Log zeigt, ob bestätigte lokale Sätze
oder unbestätigte/unklare Bestände übrig sind. Zunächst lesend prüfen:
```bash
sudo du -xhd2 /var/backups/app-backup
df -h /var/backups/app-backup
sudo find /var/backups/app-backup/archives -maxdepth 2 -name UPLOADED -printf '%h\n'
```
Unbestätigte vollständige Sätze müssen außerhalb dieses automatischen Ablaufs
gesondert geprüft und offsite veröffentlicht oder auf einen anderen Datenträger
verschoben werden. Keinen `UPLOADED`-Marker manuell vortäuschen. Reicht auch danach
der Platz nicht, das Backup-Dateisystem erweitern oder `WORKDIR`/`STAGING_ROOT`/
`ARCHIVE_DIR` auf einen ausreichend großen dedizierten Datenträger umstellen.
Eine Verlagerung erfolgt bei gestoppten Backup-/Restore-/Update-Aufträgen; vorhandene
Sätze, Besitzrechte und Modus 700 müssen erhalten bleiben. Anschließend
`--prepare-space` und `--check` mit der neuen Konfiguration ausführen.
Weder geschützte Recovery-Daten noch die letzte bestätigte lokale Sicherung
werden als Ausweg automatisch gelöscht.
Der auf Gemini gemeldete Abbruch vom 12.09.2026 erfolgte nach dem erfolgreichen
Wiederanlauf der Dienste, während der Kompression: Unter `/var` waren nur noch
9,2 GiB frei, die konfigurierte Reserve beträgt 10 GiB. Rund 29 GiB Staging und
91 GiB Archive belegten denselben Datenträger. Eine reine Reserveprüfung vor dem
Backup konnte den zusätzlichen Platzbedarf nicht erkennen.
## Neuer Ablauf
Backup, Restore und Update teilen sich dieselbe Sperre. Vor einem echten Backup
oder der Update-Vorbereitung werden folgende Schritte ausgeführt:
1. Einen unterbrochenen, eindeutig markierten monatlichen Restore-Test bereinigen.
Eine möglicherweise noch laufende Test-DB wird zuerst entfernt. Ist Docker
dafür nicht erreichbar, bleiben ihre Dateien geschützt; die Bereinigung meldet
einen Fehler und der Bereinigungsdienst versucht es erneut.
2. Erkannte Backup-Arbeitsreste früherer Läufe entfernen. Dazu müssen privates
Verzeichnis, Laufname, `meta/run-id.txt` und `meta/format.txt` zusammenpassen.
Das zugehörige unvollständige Archivverzeichnis wird ebenfalls entfernt.
Damit ist der im Gemini-Log gezeigte Fehlerfall auch aus älteren Paketständen
erkennbar. Unbekannte Ordner werden nicht anhand ihres Alters gelöscht.
3. Den Snapshot-Bedarf mit einem rsync-Trockenlauf unter denselben Excludes wie
beim Backup und einer lesenden DB-Größenabfrage schätzen. Die Planung enthält
Dateisystem-/Archiv-Metadaten, zusätzliche Dump-/Wachstumsreserven und bei
gemeinsamem Dateisystem Platz für Snapshot plus Archiv. Erst nach erfolgreicher
Platzprüfung werden produktive Writer angehalten.
4. Bei Platzmangel ältere geeignete lokale v2-Sätze prüfen. Nur Sätze mit gültigem
Manifest, `COMPLETE` und lokalem `UPLOADED` kommen infrage. Die neuesten
`SPACE_KEEP_LOCAL` geeigneten Kopien bleiben geschützt (Default und Minimum eins).
Ältere Kandidaten werden lokal vollständig validiert und mit
`rclone check --size-only` inklusive Manifest und `COMPLETE` auf
Remote-Dateiexistenz und passende Größen geprüft (ohne Archivdownload). Erst bei erfolgreicher Prüfung wird die lokale
Kopie entfernt; zusätzlich müssen Remote-Manifest und `COMPLETE` bytegenau
mit den lokalen Dateien übereinstimmen. Fehlende Remote-Dateien oder Größenabweichungen verhindern die Löschung.
Gleich große Inhaltsbeschädigungen werden erst beim Restore erkannt. Es wird nur so lange bereinigt, bis der geplante Platz reicht.
Diese Offsite-Vergleiche verwenden ebenfalls die begrenzten Prüfanläufe und
Zeitlimits aus [REMOTE_READBACK.md](REMOTE_READBACK.md). Ein fehlgeschlagener
Vergleich erlaubt auch nach mehreren Versuchen keine lokale Löschung.
Die Platzbereinigung benötigt keinen vorherigen neuen Sicherungslauf. Sie darf
das lokale Aufbewahrungsalter und `RETENTION_KEEP_LAST` unterschreiten,
**niemals die eigene Mindestanzahl `SPACE_KEEP_LOCAL`**.
Sie verändert keine Offsite-Daten. Die normale Altersretention nach einem neuen
erfolgreichen Backup bleibt davon getrennt. `--no-retention` im Update unterdrückt
die Altersretention, erlaubt aber weiterhin die hier beschriebene Platzbereinigung.
Nach dem Ende des Kopierfensters werden Dienste wie bisher wieder gestartet.
Während der Kompression wird jede Komponente vollständig als Archiv geprüft;
danach wird ihre unkomprimierte Arbeitskopie sofort entfernt. Die kleinen
Metadaten bleiben bis zum Abschluss für Veröffentlichung und Wiedererkennung.
Der Mailbericht erfasst die ursprünglichen Staging-Größen vor dieser Freigabe.
Bei einem fehlgeschlagenen Backup werden dessen Staging und unvollständige Archive
nach erfolgreicher Dienstwiederherstellung ebenfalls entfernt. Der Fehler bleibt
im Status und Bericht sichtbar. Ein vollständiger lokaler Satz, dessen Upload
fehlgeschlagen ist, bleibt erhalten.
## Grenzen der automatischen Löschung
Folgende Daten bleiben geschützt:
- vollständige lokale Sätze ohne bestätigten Upload;
- die neuesten `SPACE_KEEP_LOCAL` geeigneten lokalen Sicherungen;
- ein `.partial`-Verzeichnis, das bereits einen `COMPLETE`-Marker enthält;
- sämtliche Arbeitsreste bei vorhandenem `recovery-*.json` oder angefangener
Recovery-Datei: zunächst muss der Dienst-/Restore-Zustand geklärt werden;
- manuell entpackte Restores, historische v1-Archive und unbekannte Verzeichnisse;
- Symlink-Ziele, eingehängte Dateisysteme, fremde Container, Images und Volumes.
Es gibt kein `docker system prune`, keine pauschale Löschung von `/var/backups`
und keine automatische Entfernung von Paketrollback-Sicherungen. Die entfernte
lokale Historie wird durch einen Paketrollback nicht wiederhergestellt; ihre
geprüften Offsite-Kopien stehen weiterhin zum Download bereit.
Scheitert die Platzbeschaffung an diesen Grenzen, beendet sich das Backup vor
dem Anhalten der Writer mit einer konkreten Platzmeldung. Bei Änderungen durch
andere Prozesse oder ungewöhnlich wachsenden Dumps können spätere Prüfungen
trotzdem scheitern. Die Schätzung ist keine Dateisystemquote. Fehler bei produktiver
Dienstwiederherstellung oder einem echten Restore erfordern weiterhin einen
Admin; sie werden nicht durch automatisches Löschen oder Neustarten verdeckt.
Ein bereits vollständig lokaler, aber noch nicht hochgeladener Satz wird nicht
automatisch nachträglich hochgeladen. Solche Sätze bleiben bei wiederholten
Remote-Ausfällen erhalten und können einen Eingriff nötig machen.
## Restore und MariaDB-Vorbereitung
Der monatliche Restore-Test verarbeitet alle Komponenten einzeln. Standardmäßig
begrenzt `RESTORE_TEST_MAX_WORK_GB=0` das Arbeitsvolumen anhand der tatsächlich
freien Kapazität bei mindestens `RESTORE_TEST_MIN_FREE_GB=2` GiB Reserve. Ein
positiver Wert setzt zusätzlich eine feste Obergrenze. Die Update-Option
`--enable-restore-test` aktiviert den Test und setzt ausdrücklich das adaptive
Budget; ohne diese Option bleibt eine bestehende feste Grenze erhalten.
Vor Download und Entpacken versucht der Test bei Platzmangel die oben beschriebene
lokale Bereinigung. Während des laufenden Imports werden Grenzen überwacht;
bei Unterschreitung wird abgebrochen und bereinigt. Dabei werden nicht nebenher
Sicherungen gelöscht. Vorbereitete MariaDB-Images bleiben zur Wiederverwendung
erhalten. Ein Image-Download prüft zusätzlich Platz auf dem Docker-Dateisystem.
`app-restore.sh --remote-run ... --verify-only` lädt jeweils nur ein komprimiertes
Archiv herunter, validiert es vollständig und entfernt es sofort. Lokale
`--verify-only`-Aufrufe prüfen den Satz direkt ohne Kopie. Bei Fehlern werden die
eigenen Prüftemporärdateien entfernt; neue abgebrochene Download-Prüfungen sind
durch einen Marker beim nächsten Lauf erkennbar. Manuelle `--extract-only`- und
produktive `--apply`-Restores benötigen weiterhin Platz für ihren vollständigen
Arbeitsbestand; zusätzliche Kopier- und Entpackgrößen werden vorab geprüft. Ihre Daten werden bei Fehlern zur Prüfung erhalten und nicht
automatisch als Testreste gelöscht. Eine ausgewählte lokale Restore-Quelle ist
von der Platzbereinigung ausgenommen.
## Vorgehen auf Gemini
Das neue Update-Paket wie in [UPDATE_ANLEITUNG.md](UPDATE_ANLEITUNG.md) mit
`--enable-restore-test` starten. Es bereinigt vor der Vorprüfung erkannte alte
Arbeitsreste, bereitet MariaDB vor und führt Backup mit Remote-Dateiprüfung
aus. Nach erfolgreicher Update-Abnahme aktiviert es die Timer; der vollständige
Restore-Test folgt beim Monatstermin. Der alte fehlgeschlagene Update-Ordner
bleibt als Diagnose-/Rollback-Nachweis erhalten; ein pauschales `rm` ist unnötig.
Nach bereits erfolgter Installation kann die Platzvorbereitung separat gestartet
werden. Dieser Befehl **bereinigt tatsächlich** nach den obigen Regeln, erstellt
aber kein Backup und hält keine Anwendungen an:
```bash
sudo bash /usr/local/sbin/app-backup.sh --prepare-space
sudo bash /usr/local/sbin/app-backup.sh --check
df -h /var/backups/app-backup
```
`--check` allein bleibt eine Prüfung ohne Bereinigung. Vollständige
lokale Inhaltsprüfungen können dauern; remote werden nur Dateiexistenz und Größen geprüft. Der Starter
nennt sein Verzeichnis mit `preflight.log`; der spätere Worker schreibt `update.log`
und `result.txt`. `SUCCESS` im aktuellen `result.txt` bestätigt das Update; der
Restore-Teststatus ist ein separater Nachweis nach dem Monatslauf. Scheitert ein Update trotz der
sicheren Bereinigung, bleiben die Timer nach begonnener Installation gestoppt;
der Fehler muss behoben und das Paket erneut ausgeführt werden.