264 lines
16 KiB
Markdown
264 lines
16 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.
|
||
|
||
## Gemini: historische Archive erhalten, Staging trennen – 18.10.2026
|
||
|
||
**Reparatur vorbereitet; produktive Ausführung und vollständiger neuer Lauf noch
|
||
offen.** Die durch Johannes ausgeführte Root-Diagnose bestätigt rund 48 GB
|
||
historische flache Archive sowie drei vollständige lokale Sätze ohne `UPLOADED`.
|
||
Die Platzprüfung des Nachtlaufs bricht vor dem Snapshot ab. Diese Daten werden
|
||
nicht als automatische Löschkandidaten freigegeben.
|
||
|
||
`operations/gemini_backup_repair.py` ist eine feste Gemini-Operation. Sie wird
|
||
zusammen mit der ACME-Reparatur aus dem ai-rem-maintenance-Paket gestartet:
|
||
|
||
```bash
|
||
sudo bash /var/tmp/resume-gemini-repair-20261018.sh
|
||
sudo journalctl -fu jr-gemini-repair-20261018-r2.service --no-pager
|
||
```
|
||
|
||
Der einmalige Hintergrundauftrag erfordert das Betreiberpasswort. Quellen,
|
||
Prüfsumme und vollständiger Ablauf stehen im
|
||
[Wartungsrepository](https://gitea.jr-it-services.de/johannes/ai-rem-maintenance).
|
||
|
||
Die Speicheroperation erhält die bisherigen Archive wie folgt:
|
||
|
||
- Historische flache Archive und bei Bedarf ältere vollständige, nicht als
|
||
hochgeladen bestätigte Sätze werden auf die freie Root-Partition unter
|
||
`/srv/app-backup-preserved-20261018/` **verlagert**. Quelle und Ziel jeder Datei
|
||
werden mit SHA-256 sowie rsync-Metadatenprüfung verglichen und Zielzustand
|
||
synchronisiert. Das ursprüngliche Objekt wird erst danach entfernt; die
|
||
Sicherung bleibt unter ihrem bisherigen Namen am neuen Ort erhalten.
|
||
- Bestätigte aktuelle lokale Sätze bleiben im aktiven Archivverzeichnis. Die
|
||
Verlagerung macht aus unbestätigten Sätzen keine bestätigten Uploads. Unter
|
||
`/var/lib/jr-app-backup-space-20261018/` liegen ursprüngliche Konfiguration,
|
||
Planung und ein Prüfnachweis mit Quell-/Zielort pro Objekt, ausschließlich root-
|
||
lesbar. Alte Pfade nach einer erfolgreichen Verlagerung nicht weiterverwenden.
|
||
- `STAGING_ROOT` wechselt nach erfolgreicher Prüfung auf
|
||
`/home/.app-backup-staging`; `ARCHIVE_DIR` bleibt unter `/var`. Neue und alte
|
||
Pfade dürfen keine Backup-Quellen einschließen oder in Quellen liegen.
|
||
- Die normale gemeinsame Backup-Sperre wird gehalten. Bestehende Recovery-Marker,
|
||
belegtes Staging, unbekannte Zielkopien, Symlinks, Hardlinks, fremde Besitzer,
|
||
beschreibbare Archive und zu wenig Platz führen zum Abbruch. Vor der
|
||
Konfigurationsaktivierung laufen die echten `--prepare-space`- und `--check`-
|
||
Prüfungen mit der vorgeschlagenen Konfiguration und geerbter echter Sperre.
|
||
- `MIN_FREE_GB`, Aufbewahrung und Schätzung bleiben unverändert. Auf `/` verbleiben
|
||
mindestens die konfigurierte Reserve plus 2 GiB. Auf `/var` wird Platz für das
|
||
aktuell geschätzte Snapshotbudget plus Reserve plus 10 GiB zusätzlichen
|
||
Spielraum geschaffen. Die aktuelle Live-Schätzung ist trotzdem maßgeblich.
|
||
|
||
Danach wird der normale `app-backup.service` gestartet. Der erfolgreiche
|
||
Reparaturauftrag bestätigt nur die Vorbereitung und das Einreihen dieses Laufs.
|
||
Erst dessen `SUCCESS` einschließlich Offsite-Prüfung bestätigt die Backup-Abnahme.
|
||
Der Kopier-/Dumpabschnitt hält wie bisher die konfigurierten Writer kurz an.
|
||
|
||
Bei Teilfehlern bleiben verifizierte Zielkopien erhalten. Die alte Konfiguration
|
||
wird bis zum erfolgreichen Preflight nicht ersetzt. Eine Rücknahme der
|
||
Konfiguration allein stellt verlagerten Bestand und freien Platz nicht zurück;
|
||
kein blindes Zurückkopieren oder Löschen. Den Nachweis pro Objekt zur gezielten
|
||
Wiederherstellung beziehungsweise Auswahl historischer Restore-Quellen nutzen.
|
||
|
||
Acht lokale Tests prüfen Datei- und Verzeichnisverlagerung, Kopierkorruption
|
||
mit erhaltenem Original, Schutz vor Quellenüberschneidung/Links und Platzreserve.
|
||
Die produktive Abnahme und ein vollständiger Restore-Test stehen weiterhin aus.
|
||
|
||
### Fortsetzung nach Certbot-Abbruch
|
||
|
||
Der erste Auftrag vom 18.10.2026 scheiterte bei Certbot, bevor die
|
||
Speicheroperation begann. Revision 2 schätzt den aktuellen Bedarf lesend aus
|
||
rsync-Dateistatistiken mit denselben Excludes und aus DB-Größen. Dateimetadaten,
|
||
SQL-Ausdehnung und Wachstumsreserve entsprechen dem bestehenden Backup-Programm.
|
||
Ältere Journalzeilen werden dafür nicht benötigt; die vorhandenen echten
|
||
`--prepare-space`-/`--check`-Prüfungen bleiben die abschließende Voraussetzung.
|