Resume pending publications under local pressure, allow verified offsite-only history as a final local recovery stage, and prune old complete remote sets against actual upload quota while preserving the newest verified copies. Document defaults, recovery limits and validation; add pressure and quota regression coverage.
842 lines
48 KiB
Markdown
842 lines
48 KiB
Markdown
# Automatisches Update-Paket
|
|
|
|
## Update vom 22.10.2026: lokale Mindestkopie und knappe OneDrive-Quote
|
|
|
|
Die neue [Speicherstrategie](SPEICHER.md#adaptive-bereinigung-bei-platznot--22102026)
|
|
löst den gemeldeten Engpass durch die bisher geschützte letzte lokale Kopie.
|
|
Bei lokalem Platzdruck werden vollständige ausstehende Uploads erneut versucht.
|
|
Erst nach erfolgreicher Prüfung darf die lokale Historie vorübergehend auf null
|
|
Kopien sinken; die Offsite-Sicherung bleibt erhalten. Bei knapper gemeldeter
|
|
Remote-Quote werden ältere vollständige Sätze bis auf mindestens die neueste
|
|
geprüfte Sicherung entfernt. Normale Retention und `MIN_FREE_GB` bleiben bestehen.
|
|
|
|
Neue Defaults gelten auch ohne Ergänzung bestehender Konfigurationen:
|
|
`SPACE_ALLOW_REMOTE_ONLY=true`, `SPACE_REMOTE_CLEANUP=true`, `SPACE_KEEP_REMOTE=1`.
|
|
Mit `SPACE_ALLOW_REMOTE_ONLY=false` bleibt die bisherige lokale Mindestanzahl
|
|
verbindlich. Die neue Paket-Vorbereitung kann lokale Kopien freigeben, Uploads
|
|
wiederholen und unter Quotenmangel Remote-Sätze entfernen; `--no-retention`
|
|
unterdrückt diese Notmaßnahmen nicht. Ein reines `--check` bleibt ohne Änderungen.
|
|
|
|
Paket auf dem Entwicklungsrechner aus dem sauberen Commit bauen:
|
|
|
|
```bash
|
|
python3 tools/build-update-package.py
|
|
```
|
|
|
|
Das ausgegebene `.run` samt `.sha256` wie unten beschrieben per SCP übertragen
|
|
und als vollständiges Paket installieren. Nach Installation `result.txt` und den
|
|
neuen Backup-Bericht prüfen: erfolgreicher Lauf, Upload bestätigt, Anwendungen
|
|
wieder aktiv, Reserve erhalten. Die Abnahme vom 19.10. unten ist historisch;
|
|
für den neuen Fix ist noch kein produktiver Gemini-Lauf nachgewiesen.
|
|
|
|
## Produktive Abschlussprüfung am 19.10.2026
|
|
|
|
Die Speicherreparatur auf Gemini und der danach gestartete normale Backup-Lauf
|
|
sind erfolgreich abgenommen: `appbackup_2026-10-18_15-22-34_fe0edb31` endete
|
|
am 19.10.2026 um 03:53:28 MESZ mit `SUCCESS` und Status 0. Upload, alle 17
|
|
Remote-Dateien/-Größen und Abschlussmarker wurden bestätigt. Anwendungen und
|
|
Timer laufen wieder; der erste reguläre ai-rem-Update-Lauf bestand um 05:23:54
|
|
MESZ. [Nachweise und Grenzen](SPEICHER.md#abschlussprüfung-am-19102026).
|
|
|
|
Die folgenden älteren Abschnitte beschreiben den jeweiligen damaligen Stand.
|
|
Ein vollständiger Offsite-Restore mit isoliertem DB-Import bleibt weiterhin
|
|
offen; sein Timer ist aktiv und für den 01.11.2026 geplant.
|
|
|
|
## Update vom 25.09.2026: Laufzeit und Speicher im Mailbericht
|
|
|
|
Backup- und monatlicher Restore-Test-Mailbericht enden jetzt mit einer Übersicht
|
|
über die gesamte Verarbeitungsdauer, belegten lokalen Platz für Arbeitsbereich,
|
|
Archive, Staging, Restore, Restore-Test und Protokolle sowie freien Platz auf
|
|
jedem betroffenen Datenträger. Die Messung erfolgt nach der Bereinigung; eine
|
|
fehlgeschlagene Einzelmessung erscheint als „nicht verfügbar“. Die bisherigen
|
|
Staging- und Archivgrößen vor der Bereinigung bleiben im Backup-Bericht erhalten.
|
|
Der Report liest keine produktiven Quelldaten und ermittelt keinen belegten
|
|
Cloud-Speicher.
|
|
|
|
Das `.run`-Paket wird wie im Abschnitt
|
|
[Übertragen und starten](#übertragen-und-starten) per SCP kopiert und
|
|
installiert. Bestehende Mail-Einstellungen bleiben erhalten; neue
|
|
Konfigurationswerte sind nicht nötig. Die Mail des Abnahmebackups enthält die
|
|
neue Übersicht. Der Restore-Test erhält sie bei seinem nächsten Lauf.
|
|
|
|
Lokal bestanden ShellCheck, Syntaxprüfung und die vollständige isolierte Suite:
|
|
137 Tests, davon acht planmäßig übersprungen. Die Suite verwendet echte Archive,
|
|
eine isolierte MariaDB und lokale rclone-Crypt-Ziele. Die produktive Installation
|
|
und die Messwerte auf Gemini müssen nach dem Update anhand der Mail geprüft
|
|
werden.
|
|
|
|
## Update vom 21.09.2026: Speicherblockade auflösen
|
|
|
|
Das Paket enthält die unten beschriebenen Änderungen vom 16.09. und die neue
|
|
Speicherstrategie aus [SPEICHER.md](SPEICHER.md). Bei Platznot darf die automatische
|
|
Bereinigung jetzt bis auf `SPACE_KEEP_LOCAL=1` bestätigte lokale Sicherung
|
|
zurückgehen. Die normale Retention bleibt bei `RETENTION_KEEP_LAST=3`.
|
|
Der neue Standard gilt auch ohne Ergänzung der bestehenden Konfiguration.
|
|
Vor jeder Entfernung werden lokale Inhalte, Remote-Größen sowie Manifest und
|
|
Abschlussmarker geprüft. Die OneDrive-Sicherung wird dabei nicht gelöscht.
|
|
|
|
Die Übertragungs- und Startbefehle im folgenden Abschnitt gelten auch für dieses
|
|
Paket. Die Speicherbereinigung läuft bereits in der Paket-Vorprüfung. Es ist daher
|
|
kein vorheriges manuelles Löschen nötig. Der Starter kann für die lokale
|
|
Archivprüfung einige Zeit benötigen; das ausgegebene `preflight.log` zeigt den
|
|
Fortschritt. Bei weiterem Platzmangel enthält es eine Bestandsliste und das
|
|
verbleibende Defizit. Die Grenzen und das weitere Vorgehen stehen in `SPEICHER.md`.
|
|
|
|
Nach Installation lässt sich die Vorbereitung auch separat wiederholen:
|
|
|
|
```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
|
|
```
|
|
|
|
`--prepare-space` löscht geeignete lokale Kopien nach den beschriebenen Prüfungen.
|
|
Es stoppt keine Anwendungen und erzeugt kein neues Backup. Das eigentliche Update
|
|
erstellt dagegen ein Abnahmebackup mit Anhalten der konfigurierten Writer.
|
|
Ein Rollback stellt gelöschte lokale Kopien nicht wieder her; sie bleiben offsite.
|
|
Die Abnahme auf Gemini steht bis zum neuen `SUCCESS` in `result.txt` aus.
|
|
|
|
### Lokale Prüfung am 21.09.2026
|
|
|
|
Der Gesamtlauf bestand mit 131 Fällen (123 erfolgreich, acht planmäßig
|
|
übersprungen; 993,3 Sekunden). Danach beziehungsweise ergänzend bestanden die
|
|
zwölf abschließenden Speicher-/Retry-Tests, zwei zusätzliche Integrationsfälle
|
|
für beschädigte Rückfallkopien und Signalabbrüche sowie alle drei Tests gegen
|
|
echten Benutzer-systemd. Zusammen sind **132 unterschiedliche Tests** erfolgreich
|
|
abgedeckt. Fünf optionale Tests mit zusätzlichen Docker-Datenbankcontainern wurden
|
|
bei dieser Änderung nicht erneut ausgeführt. Die Basissuite verwendet eine echte
|
|
isolierte MariaDB und lokale rclone-Crypt-Ziele; produktive Dienste und Mailversand
|
|
werden simuliert. ShellCheck, Shell-Syntax und `git diff --check` bestanden.
|
|
|
|
Geprüft sind insbesondere die Speicherblockade bei drei lokalen Kopien,
|
|
sofortiger Bereinigungsstopp bei ausreichendem Platz, Erhalt der letzten geprüften
|
|
und aller unbestätigten Kopien, unveränderte Offsite-Daten, beschädigte Manifeste/
|
|
Marker, begrenzte Wiederholungen, Signalabbrüche und Mount-/Recovery-Schutz.
|
|
Paketinstallation, ai-rem-Einbindung und Rollback bestanden ebenfalls. Das ersetzt
|
|
nicht die noch ausstehende Installation und Speicher-/Backup-Abnahme auf Gemini.
|
|
|
|
## Ergänzung vom 18.10.2026: ai-rem-Updates beim Snapshot berücksichtigen
|
|
|
|
`--enable-ai-rem` berücksichtigt jetzt auch `ai-rem-managed-update.timer` und
|
|
`ai-rem-managed-update.service`, sofern diese auf dem Host installiert sind.
|
|
Beide werden vor den bisherigen ai-rem-Diensten gestoppt und nach dem
|
|
Anwendungsstart wieder aufgenommen. Alte Hosts ohne Update-Timer bleiben
|
|
unterstützt; wiederholte Installation erzeugt keine doppelten Stopps.
|
|
|
|
Die eigene [ai-rem-Betriebsautomatisierung](https://gitea.jr-it-services.de/johannes/ai-rem-maintenance)
|
|
richtet die täglichen Updates und einen persistenten Modell-Cache ein, verwendet
|
|
die konfigurierte `LOCKFILE` und ergänzt die Update-Units in der bestehenden
|
|
Backup-Konfiguration. Die app-backup-Ergänzung ist zusätzlich für spätere
|
|
Paketinstallationen notwendig, damit `--enable-ai-rem` die Stoppreihenfolge erhält.
|
|
Die Produktionsinstallation des ai-rem-Updaters wurde am 18.10.2026 unabhängig
|
|
bestätigt: Version 1.10.3 entspricht dem aktuellen stabilen Release,
|
|
`ai-rem-managed-update.service` endete um 11:45:36 MESZ erfolgreich und der
|
|
tägliche Timer ist aktiviert und aktiv. Cache-Lese-/Schreibrechte als
|
|
Container-Benutzer, öffentlicher Healthcheck und Remote-MCP funktionieren;
|
|
`MAX_BACKUPS=10` blieb erhalten. Laut Installer-Ausgabe wurde die vorangehende
|
|
Sicherung erfolgreich auf Gzip-Integrität und Prüfsumme geprüft. Erster geplanter
|
|
Timer-Folgelauf: 19.10.2026 um 05:25:41 MESZ. Diese Abnahme ersetzt keinen
|
|
vollständigen app-backup-/Restore-Probelauf.
|
|
|
|
## Update vom 16.09.2026: Upload ohne Archiv-Rücklesen, ai-rem wieder aufnehmen
|
|
|
|
Der tägliche Lauf lädt Archive und Manifest über Crypt hoch und prüft anschließend
|
|
Dateiexistenz und Größe mit `rclone check --size-only`. Der kleine `COMPLETE`-Marker
|
|
wird zuletzt hochgeladen und weiterhin bytegenau bestätigt. Die Platzbereinigung
|
|
verwendet ebenfalls nur Remote-Dateiexistenz und Größen. Lokale Archivprüfungen
|
|
bleiben vollständig erhalten. Es gibt keinen täglichen Download der Archive.
|
|
|
|
Auch die Update-Abnahme endet nach erfolgreichem Backup und Remote-Dateiprüfung.
|
|
Sie startet keinen Offsite-Restore mehr. `SUCCESS` in `result.txt` bestätigt daher
|
|
Installation, Backup, Upload und Dateiprüfung; der separate Inhalts- und
|
|
Wiederherstellungsnachweis entsteht beim monatlichen Restore-Test. Schäden mit
|
|
unveränderter Dateigröße können erst beim Restore erkannt werden.
|
|
|
|
`--enable-ai-rem` ergänzt die auf Gemini geprüften Pfade `/srv/ai-rem`
|
|
(einschließlich Daten, Compose-Datei und eigener Sicherungen) und `/etc/ai-rem`
|
|
(einschließlich Environment-Datei). Vorhandene `EXTRA_PATHS` bleiben in ihrer
|
|
Reihenfolge erhalten; neue Pfade werden als weitere `extra-N` angehängt.
|
|
Wiederholte Aktivierung erzeugt keine zusätzlichen Einträge dieser Pfade.
|
|
|
|
Während der Kopie werden zuerst Healthcheck-, Backup- und Prune-Timer, danach ihre
|
|
Services und `ai-rem.service` angehalten. So wird die eingebettete Datenbank bei
|
|
beendetem Container kopiert. Vorher aktive Dienste starten nach der Kopie in
|
|
umgekehrter Reihenfolge wieder. Fehlende Pfade oder Units brechen die Vorbereitung
|
|
ab. Der Monatslauf prüft und entpackt auch diese Zusatzarchive; er startet keinen
|
|
ai-rem-Anwendungscontainer und führt keinen fachlichen Datenbanktest für ai-rem aus.
|
|
Die systemd-Units und Hilfsprogramme außerhalb dieser beiden Pfade müssen für eine
|
|
Neuinstallation separat verfügbar sein.
|
|
|
|
### Übertragen und starten
|
|
|
|
Nach dem Commit wird das Paket mit `python3 tools/build-update-package.py` aus dem
|
|
sauberen Repository gebaut. Der Dateiname enthält die ersten zwölf Zeichen des
|
|
Commits. In den folgenden Befehlen `VERSION` durch diesen Wert ersetzen; die
|
|
bereitgestellte Datei liegt unter `dist/`.
|
|
|
|
Auf dem Arbeitsplatz:
|
|
|
|
```bash
|
|
cd /home/johannes/localdev/app-backup/dist
|
|
scp app-backup-update-VERSION.run app-backup-update-VERSION.run.sha256 \
|
|
johannes@gemini.jr-it-services.de:~/
|
|
```
|
|
|
|
Auf Gemini im Wartungsfenster (Anwendungen werden während der Kopie angehalten):
|
|
|
|
```bash
|
|
ssh johannes@gemini.jr-it-services.de
|
|
cd ~
|
|
sha256sum -c app-backup-update-VERSION.run.sha256 &&
|
|
sudo bash app-backup-update-VERSION.run --enable-ai-rem --enable-restore-test
|
|
```
|
|
|
|
Ein vorheriger Rollback ist nicht erforderlich. Bestehende Zugangsdaten und
|
|
Zeitpläne werden übernommen. `--enable-restore-test` stellt sicher, dass der
|
|
Monatstest aktiv ist, und bereitet sein MariaDB-Testimage vor. Diese kleine lokale
|
|
DB-Vorprüfung lädt keine Backup-Archive von OneDrive. Neue Timer laufen am ersten
|
|
Tag des Monats um 06:00 Uhr plus bis zu 15 Minuten Verzögerung; vorhandene Timer
|
|
behalten ihren Zeitplan. `Persistent=true` kann einen verpassten Monatstermin nachholen.
|
|
|
|
Der Auftrag läuft unabhängig von SSH. Verlauf und Ergebnis:
|
|
|
|
```bash
|
|
sudo journalctl -fu app-backup-upgrade.service --no-pager
|
|
# Strg+C beendet nur die Loganzeige.
|
|
# Den tatsächlichen Ergebnisordner aus der Starter-Ausgabe einsetzen:
|
|
sudo cat /var/backups/app-backup-upgrade-XXXXXXXX/result.txt
|
|
sudo systemctl list-timers app-backup.timer app-restore-test.timer --no-pager
|
|
```
|
|
|
|
Erst `SUCCESS` in der neuen `result.txt` bestätigt den Abschluss. Bei `QUEUED` oder
|
|
`RUNNING` keinen zweiten Auftrag starten. Der abgenommene Lauf steht in
|
|
`uploaded-backup-run`; ein neuer Restore-Erfolg wird beim Update nicht behauptet.
|
|
Nach dem Monatstest stehen Ergebnis und letzte erfolgreiche Probe unter
|
|
`/var/backups/app-backup/restore-test/state.json` und `last-success.json`.
|
|
|
|
Der fehlgeschlagene lokale Satz `appbackup_2026-09-15_21-03-40_21b6efeb`
|
|
bleibt erhalten. Das Update veröffentlicht ihn nicht nachträglich und setzt
|
|
seinen fehlenden `UPLOADED`-Nachweis nicht künstlich. Es erstellt einen neuen Lauf.
|
|
|
|
### Historische Fehleranalysen bis 15.09.2026
|
|
|
|
Die folgenden Nachträge beschreiben den damaligen Ablauf einschließlich sofortiger
|
|
Rücklese- und Restore-Abnahme. Für neue Installationen gilt der oben beschriebene
|
|
Ablauf vom 16.09.; die damaligen Paketnamen sind keine aktuelle Installationsanweisung.
|
|
|
|
## Nachtrag vom 15.09.2026: Healthcheck verdrängt Apache-Stop
|
|
|
|
Im Update mit Paket `3d16f33f24c0` wurde die alte Sicherung vom 12.09. um
|
|
14:29:24 MESZ im dritten Rückleseversuch vollständig bestätigt (16 Dateien,
|
|
keine Unterschiede). Erst danach entfernte die Platzbereinigung ihre lokale
|
|
Kopie. Die neue Installation und ihre Vorprüfung waren erfolgreich.
|
|
|
|
Der anschließende Abnahmelauf `appbackup_2026-09-15_12-29-36_75975f52` brach
|
|
bereits beim Anhalten der Writer ab: Um 14:29:56 stoppte das Backup `httpd`;
|
|
um 14:30:00 meldete `ai-rem-healthcheck.service` einen fehlgeschlagenen öffentlichen
|
|
Healthcheck und veranlasste einen Apache-Reload. Dieser verdrängte den laufenden
|
|
Stop-Auftrag (`Job for httpd.service canceled`). Ein neues Backup oder dessen
|
|
Restore-Test wurde in diesem Lauf noch nicht fertiggestellt. Die Fehlerbereinigung
|
|
schaltete den Nextcloud-Wartungsmodus aus und startete Apache und Cron wieder.
|
|
Backup- und Restore-Test-Timer blieben wegen der fehlenden Abnahme gestoppt.
|
|
|
|
Die Korrektur schützt jeden Writer-Stop mit
|
|
`systemctl stop UNIT --job-mode=replace-irreversibly`. Die vorhandene
|
|
`ConditionPathExists` verhindert Starts während der Kopie, schützt aber allein
|
|
keinen noch laufenden Stop-Auftrag gegen einen Reload. Der zusätzliche Jobmodus
|
|
verhindert dessen Verdrängung, solange der Stop läuft. Er setzt keine dauerhafte
|
|
Maskierung, ändert keine Stop-Zeitlimits und verhindert den normalen Wiederanlauf
|
|
nach Freigabe der Startsperren nicht. Ein explizites `systemctl cancel` oder ein
|
|
echter Stopfehler bleibt ein Abbruchgrund. Siehe die
|
|
[systemd-Dokumentation zum Jobmodus](https://github.com/systemd/systemd/blob/v257/man/systemctl.xml).
|
|
|
|
Ein Regressionstest gegen echten Benutzer-systemd reproduziert den alten
|
|
Reload-Konflikt trotz gesetzter Startbedingung und prüft den korrigierten Stop
|
|
gegen Reload und Start. Die Container-Tests prüfen weiterhin die Wiederaufnahme
|
|
nach Stopfehlern und die Konsistenzsperren während der Kopie.
|
|
|
|
Lokale Verifikation am 15.09.2026: 119 Fälle im Container-Standardlauf, davon
|
|
111 erfolgreich und acht planmäßig übersprungen (fünf separate
|
|
Docker-Integrationstests und drei Benutzer-systemd-Tests); Laufzeit 906,3 Sekunden.
|
|
Die drei Benutzer-systemd-Tests bestanden separat und prüfen auch den inaktiven
|
|
Dienstzustand nach dem geschützten Stop. ShellCheck und Shell-Syntaxprüfung
|
|
bestanden. Die Serverabnahme dieser Korrektur steht noch aus.
|
|
|
|
Das neue Paket wie unten per SCP übertragen und normal starten; ein vorheriger
|
|
Rollback ist nicht erforderlich. Der Healthcheck muss für diese Korrektur nicht
|
|
dauerhaft abgeschaltet werden. Der Installer erstellt erneut ein Abnahmebackup
|
|
und führt den vollständigen Restore-Test aus. Erst `SUCCESS` in seiner neuen
|
|
`result.txt` bestätigt den Abschluss und die Timer-Aktivierung. Diese Korrektur
|
|
betrifft den Dienststopp; die ursprüngliche OneDrive-Ursache bleibt ungeklärt.
|
|
|
|
## Nachtrag vom 15.09.2026: Restore-Abnahme nach erfolgreichem Backup
|
|
|
|
Das Paket `4f220dbc6447` bestand auf Gemini das neue Backup einschließlich
|
|
vollständiger Remote-Rückleseprüfung. Danach scheiterte der separate Restore-Test
|
|
bei `nextcloud-data` mit `Command failed: bash`; seine Bereinigung war erfolgreich.
|
|
Die erste Korrektur erfasste diesen eigenen Downloadpfad noch nicht.
|
|
|
|
Das aktuelle Paket begrenzt und wiederholt auch die Restore-Test-Downloads.
|
|
Es meldet die genaue Komponente/Phase, Exit-Code, empfangene Bytes und sichere
|
|
Fehlerklassen. Angefangene Downloads werden vor Wiederholung auf null gekürzt.
|
|
Details und Grenzen stehen in [RESTORE_TEST.md](RESTORE_TEST.md).
|
|
|
|
Bei diesem Updatefehler bleibt das erfolgreich erstellte Backup erhalten,
|
|
das Paket ist installiert, Backup- und Restore-Test-Timer bleiben jedoch gestoppt.
|
|
Das korrigierte Paket wie unten per SCP übertragen und im Wartungsfenster normal
|
|
starten. Es erstellt ein neues Abnahmebackup und prüft dieses vollständig.
|
|
Ein bereits aktivierter Restore-Test benötigt keine weitere Aktivierungsoption.
|
|
Erst `SUCCESS` in der **neuen** `result.txt` bestätigt die gesamte Update-Abnahme
|
|
und die Timer-Aktivierung; die alte Fehlerdatei bleibt ein historischer Nachweis.
|
|
Rollback ist für die erneute Paketinstallation nicht erforderlich.
|
|
|
|
## Korrektur vom 15.09.2026: hängende Rückleseprüfung
|
|
|
|
Das aktuelle Paket ergänzt drei vollständige Rückleseversuche mit eigenen
|
|
Zeitlimits und Dateiergebnissen. Bestehende Konfigurationen erhalten die neuen
|
|
Defaults automatisch; `RCLONE_TIMEOUT="1h"` für sonstige rclone-Aufrufe wird
|
|
dabei nicht umgeschrieben. Analyse, Grenzwerte und Prüfung des fehlgeschlagenen
|
|
Satzes stehen in [REMOTE_READBACK.md](REMOTE_READBACK.md).
|
|
|
|
Das Paket wie unten beschrieben im Wartungsfenster starten. Ein bereits
|
|
aktivierter monatlicher Restore-Test bleibt aktiv und wird bei der Abnahme
|
|
ausgeführt. Für diese Korrektur ist `--enable-restore-test` nicht zusätzlich nötig.
|
|
Erst `SUCCESS` in `result.txt` bestätigt die gesamte Abnahme. Der fehlgeschlagene
|
|
Satz vom 15.09. wird durch die Installation nicht nachträglich veröffentlicht.
|
|
|
|
## Neu: monatlicher Restore-Test
|
|
|
|
Das Paket enthält jetzt den automatischen vollständigen Offsite-Restore-Test.
|
|
Wegen des knappen Speichers arbeitet er Komponenten einzeln ab und entfernt
|
|
jeweils Archiv, entpackte Daten und Test-DB. Auch Fehler- und Abbruchpfade besitzen
|
|
eine Bereinigung. Es bleiben nur kleine, begrenzte Betriebsnachweise.
|
|
|
|
Mit `--enable-restore-test` übernimmt der Installer die MariaDB-Vorbereitung:
|
|
Produktionsserie lesen, passendes lokales Image wiederverwenden oder laden und
|
|
einen isolierten Probeimport einschließlich Bereinigung ausführen. Manuelles
|
|
`docker pull` ist auf Gemini nicht mehr erforderlich. Die Option aktiviert
|
|
zugleich das adaptive Arbeitsbudget; Details: [RESTORE_TEST.md](RESTORE_TEST.md).
|
|
Nach erfolgreichem Backup mit Remote-Dateiprüfung aktiviert der Worker
|
|
Monatstimer und Boot-Bereinigung. Der vollständige Offsite-Restore folgt beim Monatstermin.
|
|
|
|
Vor der Vorprüfung werden erkannte Überreste fehlgeschlagener Backups bereinigt
|
|
und der nächste Snapshot geplant. Reicht der Platz nicht, werden geeignete ältere
|
|
lokale Kopien nach lokaler Inhaltsprüfung und Remote-Datei-/Größenprüfung entfernt; die neuesten
|
|
`RETENTION_KEEP_LAST` bleiben geschützt. Diese Platzbereinigung gilt auch während
|
|
einer Update-Abnahme ohne reguläre Retention. Sie wird nicht durch Paketrollback
|
|
rückgängig gemacht; entfernte vollständige lokale Sätze bleiben offsite verfügbar.
|
|
[SPEICHER.md](SPEICHER.md) dokumentiert Grenzen und den Gemini-Fehlerfall.
|
|
Bestehende Konfigurationen ohne `ENABLE_RESTORE_TEST` bleiben deaktiviert.
|
|
Bestehende Restore-Test-Zeitpläne werden erhalten; neue Vorlagen liegen als `.dist`
|
|
daneben. Bei einem Paketrollback werden die Test-Timer/-Bereinigungs-Units vor dem
|
|
Zurückspielen deaktiviert und die vorherigen Dateien wiederhergestellt. Den
|
|
gewünschten Zeitplan danach anhand des zurückgespielten Paketstands prüfen.
|
|
|
|
## Paket starten
|
|
|
|
Für Gemini zuerst `MAIL_HOSTNAME="gemini.jr-it-services.de"` in der aktiven
|
|
Konfiguration setzen: [Mailberichte nach dem Update](#mailberichte-nach-dem-update).
|
|
|
|
Auf dem Arbeitsplatz die gelieferte `.run`-Datei und ihre `.sha256`-Datei per SCP
|
|
auf den Server übertragen. Auf dem Server im selben Verzeichnis prüfen/starten:
|
|
|
|
```bash
|
|
sha256sum -c app-backup-update-VERSION.run.sha256
|
|
sudo bash app-backup-update-VERSION.run --enable-ai-rem --enable-restore-test
|
|
```
|
|
|
|
VERSION durch den tatsächlichen Dateinamen ersetzen. Ein Git-Checkout auf dem
|
|
Server ist nicht erforderlich. Der Installer benötigt die vorhandene Konfiguration
|
|
`/etc/app-backup/app-backup.conf` und die bisherigen aktiven Zugangsdaten.
|
|
|
|
Der Start ist die Freigabe für das Update einschließlich eines vollständigen
|
|
Backups mit zeitweiliger Unterbrechung der konfigurierten Anwendungen.
|
|
|
|
## Was automatisch passiert
|
|
|
|
Nach dem erfolgreichen Gemini-Lauf wurden Fortschrittsmeldungen, eine Prüfung
|
|
exportierter rclone-Optionen und der bytegenaue Vergleich des Abschlussmarkers
|
|
ergänzt. Für diese Härtung das aktuelle Paket im
|
|
vereinbarten Wartungsfenster über denselben Installer installieren; die bestehenden
|
|
Zugangsdaten und der Zeitplan bleiben erhalten. Der Installer führt erneut ein
|
|
vollständiges Abnahmebackup durch. Die technische Abnahme des bisherigen Satzes
|
|
bleibt gültig; der einmalige, überwundene HTTP-409 allein erfordert keinen Neustart.
|
|
|
|
Falls die neue Vorprüfung `Unsupported rclone environment override` meldet,
|
|
die genannte Einstellung in Shell oder systemd-Umgebung prüfen und entfernen
|
|
beziehungsweise in eine unterstützte Backup-Einstellung überführen. Keine
|
|
Optionswerte oder Zugangsdaten ins Protokoll kopieren. Globale rclone-Filter und
|
|
`RCLONE_SIZE_ONLY` können Sicherungsumfang beziehungsweise Inhaltsprüfung
|
|
abschwächen und sind im Backup-Prozess nicht unterstützt.
|
|
|
|
1. Paketinhalt per SHA-256 prüfen und geschützt unter `/var/tmp` entpacken.
|
|
2. Bestehende Einstellungen nach `/var/backups/app-backup-upgrade-XXXXXXXX` sichern.
|
|
3. Aktuelle Pfade und Einstellungen übernehmen; sichere Betriebsoptionen ergänzen.
|
|
4. Vorhandene Webdienste und direkt erkennbare Nextcloud-systemd-Writer zuordnen.
|
|
5. Crypt-Konfiguration, DB-Dateien, globales DB-Recht `RELOAD` und bei MariaDB
|
|
Zugriff auf Routinen-Metadaten prüfen;
|
|
vorhandene Schlüssel/Passwörter erhalten. Keine automatischen DB-Grants.
|
|
6. Sichere Platzbereinigung und Bedarfsplanung unter gemeinsamer Sperre ausführen, dann Vorprüfung mit geschützten Kopien durchführen. rsync prüft außerdem den Zugriff
|
|
auf Quellverzeichnisse und deren Attribute in einem privaten temporären
|
|
Prüfbereich, ohne Datei-Inhalte zu kopieren. Bei Fehlern bleibt das installierte
|
|
Paket samt Anwendungskonfiguration und Timer unverändert.
|
|
7. Einen von SSH unabhängigen systemd-Auftrag `app-backup-upgrade.service` mit
|
|
`--no-block` einreihen und die Sperren an ihn übergeben.
|
|
8. Backup-Timer stoppen, Paket mit Rollback-Inventar installieren, Konfiguration
|
|
atomar übernehmen und Rechte der aktiven root-eigenen Zugangsdaten korrigieren.
|
|
9. Vollständiges Backup ohne reguläre lokale/Remote-Altersretention durchführen.
|
|
Platzbereinigung bleibt erlaubt. Upload mit anschließender Dateiexistenz-/
|
|
Größenprüfung und Bestätigung des Abschlussmarkers; keine Archivdownloads.
|
|
10. Erst bei Erfolg den Backup-Timer aktivieren und das Ergebnis protokollieren.
|
|
|
|
Es findet kein Import in produktive Anwendungen oder Datenbanken statt. Der
|
|
Update-Prüflauf bestätigt den Upload. Entpacken und DB-Import werden separat
|
|
beim Monatslauf geprüft; ein fachlicher Anwendungstest bleibt zusätzlich erforderlich.
|
|
|
|
## Verlauf und Ergebnis
|
|
|
|
```bash
|
|
sudo journalctl -fu app-backup-upgrade.service --no-pager
|
|
```
|
|
|
|
Der Starter nennt außerdem den **konkreten** Ergebnisordner:
|
|
|
|
```bash
|
|
sudo cat /var/backups/app-backup-upgrade-XXXXXXXX/result.txt
|
|
sudo less /var/backups/app-backup-upgrade-XXXXXXXX/update.log
|
|
```
|
|
|
|
Erwartet wird `SUCCESS`. Bei `QUEUED` oder `RUNNING` nicht parallel erneut starten.
|
|
`QUEUED` bedeutet, dass der Auftrag zur Übergabe vorbereitet wurde und noch kein
|
|
Worker den Start bestätigt hat. Ein erfolgreicher Starter bestätigt nur die
|
|
Annahme durch systemd; Installation und Backup können anschließend noch scheitern.
|
|
Nach Ende verschwindet die kurzlebige systemd-Unit durch `--collect` auch bei
|
|
Fehlern. `Unit ... could not be found` ist daher kein Erfolgsnachweis und verhindert
|
|
die Journalabfrage nicht. Log und Ergebnis bleiben erhalten. Diagnose ohne Pager:
|
|
|
|
```bash
|
|
sudo journalctl -u app-backup-upgrade.service -n 100 --no-pager -l
|
|
sudo systemctl status app-backup-upgrade.service --no-pager -l
|
|
```
|
|
|
|
Bleibt `QUEUED` stehen, zuerst das Journal prüfen: Ein Fehler noch vor dem Start
|
|
des Bash-Workers (z. B. ein nicht ausführbarer Paketpfad) kann noch nicht in
|
|
`update.log` oder `result.txt` durch den Worker protokolliert werden. Ein späterer
|
|
Sperr-Timeout erscheint dagegen in beiden Dateien. Nicht allein auf den Exit-Code
|
|
von `systemd-run` vertrauen.
|
|
`--foreground` führt den Vorgang stattdessen im aktuellen Terminal aus und ist
|
|
für Tests/Diagnose gedacht; dabei besteht keine Absicherung gegen SSH-Abbruch.
|
|
|
|
## Gezielte Rückfragen und Grenzen
|
|
|
|
### Mailberichte nach dem Update
|
|
|
|
Für den gewünschten Gemini-Hostnamen **vor dem Paketstart** die aktive
|
|
Konfiguration mit `sudoedit /etc/app-backup/app-backup.conf` öffnen und folgende
|
|
Zeile ergänzen beziehungsweise den vorhandenen Wert ersetzen:
|
|
|
|
```bash
|
|
MAIL_HOSTNAME="gemini.jr-it-services.de"
|
|
```
|
|
|
|
Danach Prüfsumme kontrollieren und das neue `.run`-Paket wie am Anfang der Anleitung
|
|
beschrieben starten. Der Installer erhält diesen Wert und die Mail des
|
|
Abnahmebackups zeigt bereits
|
|
`[app-backup] SUCCESS gemini.jr-it-services.de appbackup_2026-…` sowie
|
|
`Host: gemini.jr-it-services.de` im Nachrichtentext. Bei einem Fehler steht
|
|
entsprechend `FAIL` im Betreff. Ohne Einstellung oder bei `MAIL_HOSTNAME=""`
|
|
bleibt die automatische Ermittlung über `socket.getfqdn()` aktiv.
|
|
Der Absender wird weiterhin ausschließlich durch `MAIL_FROM` beziehungsweise
|
|
den bisherigen Standard `app-backup@<System-FQDN>` bestimmt. Systemhostname und
|
|
Archivnamen werden nicht geändert. Nach Installation des neuen Codes genügt
|
|
für spätere Anpassungen eine Konfigurationsänderung vor dem nächsten Lauf.
|
|
|
|
Das Paket stellt die ausführlichen Mailberichte wieder bereit. Vorhandene Werte
|
|
für `ENABLE_MAIL_REPORT`, `MAIL_TO`, `MAIL_FROM`, `MAIL_HOSTNAME`, `MAIL_SUBJECT_PREFIX` und
|
|
`MAIL_INCLUDE_LOG_TAIL_LINES` bleiben erhalten; sie müssen nicht neu eingegeben
|
|
werden. Eine bislang deaktivierte Berichtsfunktion bleibt deaktiviert. Fehlende
|
|
Absender-/Betreff-/Tail-Einstellungen erhalten die in README beschriebenen Defaults.
|
|
Die neue Python-Berichtskomponente wird vom Installer samt Rollback installiert.
|
|
|
|
Beim Abnahmebackup entsteht eine Mail mit Laufzeit, Größen, Upload-Prüfstatus und
|
|
Log-Auszug. Das Update ist erst mit `SUCCESS` in seiner `result.txt` nach der
|
|
Remote-Dateiprüfung abgeschlossen. Fehlt die Mail, im Backup-Log nach
|
|
`mail report failed` suchen und die lokale `report_LAUF.eml`, sendmail-Verfügbarkeit,
|
|
MTA-Queue und Empfänger-/Aliaszustellung prüfen. Keine erneute Sicherung allein
|
|
zum Testen der Mailzustellung starten. Die Entwicklungstests verwenden eine lokale
|
|
MTA-Attrappe und versenden keine echten Nachrichten.
|
|
|
|
### Quellen und Writer
|
|
|
|
- **Zentrales Mailverzeichnis fehlt, etwa `/var/vmail`:** Der Installer fragt vor
|
|
der Installation nach dem tatsächlichen absoluten Pfad. Alternativ lässt sich
|
|
dieser mit `--mail-dir /tatsaechliche/mailablage` übergeben. Kein leeres
|
|
Ersatzverzeichnis anlegen: Das würde fehlende Maildaten nur verdecken.
|
|
Liegen **alle** Mailboxen in den angezeigten `MAIL_HOME_DIRS`, im Dialog `homes`
|
|
wählen und die vollständige Abdeckung bestätigen. `--mail-homes-only` erteilt
|
|
dieselbe ausdrückliche Bestätigung ohne Dialog. Dabei müssen die Home-Sicherung
|
|
aktiviert und alle konfigurierten Homes vorhanden sein. Excludes und
|
|
Dateisystemgrenzen gelten weiterhin; ausgeschlossene Verzeichnisse, verlinkte
|
|
externe Mailablagen und weitere Mounts sind dadurch nicht abgedeckt.
|
|
Postfix/Dovecot-Konfigurationen und Maildienst-Stopps bleiben aktiv.
|
|
Bei unbekannter Mailablage abbrechen und zuerst die Mailserver-Konfiguration
|
|
prüfen. Ein fehlender Pfad wird nie automatisch übersprungen.
|
|
- **Rclone-Datei nicht eindeutig:** Pfad im Dialog oder mit `--rclone-config FILE`
|
|
angeben. Eine user-eigene Datei wird in eine neue root-eigene Datei kopiert;
|
|
die vom Benutzer verwendete Originaldatei bleibt unverändert.
|
|
- **Gitea bisher nicht konfiguriert:** Aufnahme bestätigen oder bewusst
|
|
`--no-gitea` setzen. Absolute explizite Pfade und der MySQL-DB-Name können aus
|
|
`app.ini` übernommen werden. Mehrdeutige/relative Pfade müssen zuerst in der
|
|
vorhandenen Backup-Konfiguration ergänzt werden; es werden keine geratenen
|
|
Repository-Pfade eingetragen.
|
|
- **Nextcloud in crontab:** Der Installer fragt, ob der gefundene Cron-Dienst
|
|
während jeder Sicherung angehalten werden darf. Das betrifft auch andere
|
|
Cronjobs; währenddessen fällige Jobs können ausfallen. Alternativ Nextcloud
|
|
zuvor in einen eigenen systemd-Service/Timer übertragen. Bereits gestartete
|
|
direkte `cron.php`-/`occ`-Prozesse werden nach dem Writer-Stopp abgewartet
|
|
(Default 300 Sekunden), nicht blind beendet. Shell-Wrapper, externe Scheduler
|
|
und nicht direkt erkennbare Writer müssen explizit berücksichtigt werden.
|
|
- **Fehlende Basispakete:** Installation über `dnf` nach Rückfrage oder mit
|
|
`--install-deps`. Keine automatische Aktualisierung von PHP, DB-Server oder
|
|
rclone auf eine möglicherweise inkompatible Version.
|
|
- **Verschlüsselte rclone-Konfigurationsdatei:** Die für rclone benötigte
|
|
Entsperrung muss auch im systemd-Kontext verfügbar sein. Ohne verfügbare
|
|
Entsperrung bricht die Prüfung ab, statt unsichtbar auf eine Passworteingabe zu warten. Der Installer legt
|
|
keine neuen Crypt-Passwörter an und exportiert keine fremden Secret-Stores.
|
|
- **Früher eingecheckte DB-Passwörter:** Passwortrotation bleibt separat, weil
|
|
weitere Benutzer derselben Accounts nicht zuverlässig ermittelt werden können.
|
|
|
|
Optionen können kombiniert werden:
|
|
|
|
```bash
|
|
sudo bash app-backup-update-VERSION.run \
|
|
--rclone-config /root/.config/rclone/rclone.conf \
|
|
--enable-gitea --cron-services nextcloudcron.timer,nextcloudcron.service
|
|
```
|
|
|
|
Die Remote-Retention bleibt nach der Migration ausgeschaltet. Nach einem echten
|
|
Test-Restore bei Bedarf bewusst wieder aktivieren. Bestehende Timer-Zeitpläne
|
|
bleiben erhalten; beim Aktivieren kann `Persistent=true` einen Lauf nachholen.
|
|
|
|
## Fehler und Rückweg
|
|
|
|
### Startfehler nach genau 60 Sekunden bei älteren Paketen
|
|
|
|
Die Pakete `8e6c9a058fa9` und `56fbcdad74f4` enthielten einen Fehler in der
|
|
systemd-Übergabe: Der Starter hielt die Update-Sperre und wartete synchron auf
|
|
den Abschluss des Startauftrags einer `Type=oneshot`-Unit. Dieser Startauftrag
|
|
endet erst mit dem Worker; der Worker wartete aber selbst auf die Sperre des
|
|
Starters. Nach 60 Sekunden brach seine Sperranforderung ab, noch vor Installation
|
|
und Timer-Stopp. In diesem Ablauf ist kein Rollback erforderlich. Der ursprüngliche
|
|
Worker hatte vor dem Sperrwarten noch kein eigenes Log eingerichtet, daher konnte
|
|
die Fehlermeldung auf den systemd-Exit-Code beschränkt bleiben.
|
|
|
|
Das korrigierte Paket verwendet `systemd-run --no-block` und gibt zuerst die
|
|
Backup-Sperre, dann die Update-Sperre frei. Eine fehlgeschlagene Übergabe entzieht
|
|
auch einem möglicherweise schon eingereihten Worker die Freigabe. Die Sperren
|
|
bleiben als Schutz vor parallelen Backups/Updates erhalten. Erneut das **neue**
|
|
Paket starten; weder Sperrdateien löschen noch alte Worker manuell nachstarten.
|
|
|
|
Das Verhalten von `--no-block` und `--collect` ist in der
|
|
[systemd-Dokumentation](https://github.com/systemd/systemd/blob/v256/man/systemd-run.xml)
|
|
beschrieben, der Startabschluss von `oneshot` in
|
|
[systemd.service](https://github.com/systemd/systemd/blob/v256/man/systemd.service.xml).
|
|
|
|
### Fehlende Mailablage und erneuter Start
|
|
|
|
Ein Abbruch `Missing source: /var/vmail` bei der **Vorprüfung**, wie beim Paket
|
|
`8e6c9a058fa9`, erfordert kein Rollback. Mit dem korrigierten Paket erneut starten
|
|
und die Mailablage klären. Die bisherige Konfiguration und der Timer sind erhalten;
|
|
der abgebrochene Versuch enthält noch kein erfolgreiches neues Backup.
|
|
Bereits bewusst getroffene Entscheidungen können als Optionen mitgegeben werden:
|
|
|
|
```bash
|
|
sudo bash app-backup-update-VERSION.run --enable-gitea --cron-services crond.service
|
|
```
|
|
|
|
Diese Optionen passen nur, wenn Gitea aufgenommen werden soll und das Pausieren
|
|
aller Cronjobs über `crond.service` ausdrücklich akzeptiert wurde.
|
|
|
|
Für Mailablagen wie `/home/johannes/Mail` unter den konfigurierten Benutzerhomes
|
|
zusätzlich `--mail-homes-only` verwenden, sofern damit alle Postfächer erfasst sind:
|
|
|
|
```bash
|
|
sudo bash app-backup-update-VERSION.run \
|
|
--enable-gitea --cron-services crond.service --mail-homes-only
|
|
```
|
|
|
|
Der Installer zeigt die übernommenen Home-Verzeichnisse an. `Mail/` einschließlich
|
|
`cur`, `new`, `tmp` und Dovecot-Dateien wird mit den normalen Home-Excludes der
|
|
Vorlage vollständig kopiert, sofern es auf demselben Dateisystem liegt und kein
|
|
Verweis auf eine externe Ablage ist. Weitere Benutzer müssen in `MAIL_HOME_DIRS`
|
|
stehen; das Vorhandensein eines einzelnen Postfachs belegt nicht deren Abdeckung.
|
|
|
|
### Fehler nach Installationsbeginn
|
|
|
|
Bei einem Fehler nach Beginn der Installation bleibt der Backup-Timer gestoppt.
|
|
Es erfolgt kein automatisches Zurücksetzen über möglicherweise noch laufende oder
|
|
teilweise wiederhergestellte Anwendungen. Logs und gegebenenfalls
|
|
`recovery-*.json` im Workdir prüfen. Das kombinierte Rollback stellt die vorherigen
|
|
Paketdateien **und** die vorherige Backup-Hauptkonfiguration wieder her:
|
|
|
|
```bash
|
|
sudo bash /var/backups/app-backup-upgrade-XXXXXXXX/rollback-update.sh
|
|
```
|
|
|
|
Es verändert keine gesicherten Anwendungsdaten, rotiert keine Zugangsdaten und
|
|
startet den Timer nicht ungeprüft. Neu erzeugte root-eigene Kopien von rclone-Dateien
|
|
sowie strengere Dateirechte bleiben erhalten. Bei unterbrochener Vorbereitung
|
|
ohne Installationsbeginn ist kein Paket-Rollback erforderlich.
|
|
|
|
### Fehlendes DB-Recht RELOAD
|
|
|
|
`mariadb-dump: ... FLUSH ... Access denied ... RELOAD ... (1227)` bedeutet:
|
|
Die Anmeldung funktioniert, aber dem tatsächlich verwendeten DB-Konto fehlt das
|
|
globale Sperrrecht für `--lock-all-tables`. Ein pauschaler Wechsel auf einen Dump
|
|
ohne Sperren oder ausschließlich `--single-transaction` ist bei gemischten
|
|
Storage Engines kein gleichwertiger Ersatz. Das neue Paket prüft `RELOAD` bereits
|
|
vor Installation und Wartungsmodus über lesende Privileg-Metadaten.
|
|
|
|
Die tatsächlich authentifizierten Konten und Serverversionen ermitteln. Zunächst
|
|
eine Root-Shell starten:
|
|
|
|
```bash
|
|
sudo bash
|
|
```
|
|
|
|
Erst in dieser Shell den folgenden Block ausführen. Er gibt keine Passwörter
|
|
oder Authentifizierungshashes aus und beendet anschließend die Root-Shell:
|
|
|
|
```bash
|
|
source /etc/app-backup/app-backup.conf
|
|
query='SELECT CURRENT_USER(), VERSION()'
|
|
echo WordPress
|
|
mariadb --defaults-extra-file="$WP_DB_CNF" -N -B -e "$query"
|
|
echo Nextcloud
|
|
mariadb --defaults-extra-file="$NC_DB_CNF" -N -B -e "$query"
|
|
echo Gitea
|
|
mariadb --defaults-extra-file="$GITEA_DB_CNF" -N -B -e "$query"
|
|
exit
|
|
```
|
|
|
|
Nur die Zeilen für tatsächlich konfigurierte Anwendungen ausführen. Die getrennte
|
|
Root-Shell vermeidet Probleme durch kopierte Einrückungen an Here-Doc-Abschlussmarken.
|
|
|
|
Mit einem DB-Administratorkonto nur die betroffenen, vorhandenen Backup-Konten
|
|
berechtigen. Beispiel für das **zuvor tatsächlich identifizierte** Konto
|
|
`backup@localhost` (nicht ungeprüft übernehmen):
|
|
|
|
```sql
|
|
GRANT RELOAD ON *.* TO 'backup'@'localhost';
|
|
```
|
|
|
|
`RELOAD` ist ein globales Verwaltungsrecht zum Flush/Reload; deshalb wird es nicht
|
|
automatisch durch den Paketinstaller vergeben. Keine pauschalen `ALL PRIVILEGES`
|
|
oder `GRANT OPTION` erteilen. Wenn die CNF ein produktives Anwendungskonto verwendet,
|
|
ein separates Backup-Konto mit gezielten Rechten vorbereiten. Ein zusätzliches
|
|
`FLUSH PRIVILEGES` ist nach `GRANT` nicht notwendig. Quelle:
|
|
[MariaDB GRANT](https://mariadb.com/docs/server/reference/sql-statements/account-management-sql-statements/grant).
|
|
|
|
Für MariaDB prüft das Paket außerdem den Lesezugriff auf `mysql.proc`, den die
|
|
verwendete Option `--routines` benötigt. Falls dieser fehlt, gezielt für das
|
|
identifizierte Backup-Konto vergeben:
|
|
|
|
```sql
|
|
GRANT SELECT ON mysql.proc TO 'backup'@'localhost';
|
|
```
|
|
|
|
Auch dies ist ein Beispiel mit zu ersetzendem Kontonamen. Es erlaubt den Zugriff
|
|
auf Routinen-Metadaten datenbankübergreifend; kein `SELECT ON mysql.*` vergeben.
|
|
Quelle: [MariaDB mariadb-dump / routines](https://mariadb.com/docs/server/clients-and-utilities/backup-restore-and-import-clients/mariadb-dump).
|
|
|
|
Weitere erforderliche Rechte hängen von Views, Triggern und Events ab;
|
|
`RELOAD` allein ersetzt keine Leserechte auf den zu sichernden Datenbanken.
|
|
Die neue Prüfung deckt die globale Sperrberechtigung und MariaDB-Routinen-Metadaten
|
|
ab, nicht sämtliche möglichen Objektrechte. Der vollständige Abnahmelauf bleibt verpflichtend.
|
|
|
|
Beim gemeldeten Lauf vom 10.09.2026 um 14:41 Uhr war das Paket bereits installiert,
|
|
als der erste Dump scheiterte. Nextcloud verließ laut Log den Wartungsmodus und
|
|
Cron wurde wieder gestartet. Das ist **kein erfolgreiches Backup**; der Timer
|
|
bleibt bis zur Abnahme gestoppt. Nach Rechtekorrektur das aktuelle Paket erneut
|
|
starten: Es prüft, sichert und aktiviert den Timer erst nach erfolgreicher
|
|
Remote-Prüfung. Ein erneuter Paketlauf erhält die ursprüngliche Sicherung des
|
|
vorigen Update-Versuchs. Für einen Rückweg zum Stand vor dem ersten Installationslauf
|
|
ist dessen Rollback-Ordner maßgeblich; ein späterer Snapshot enthält bereits die
|
|
zuvor installierte Version.
|
|
|
|
Dienst-Stopps/-Starts und das Warten auf Nextcloud-Writer werden jetzt ausdrücklich
|
|
im Journal protokolliert. Eine längere Pause ohne CPU-Last lässt sich so einem
|
|
konkreten Dienst zuordnen; ohne dessen Journal lässt sich die Ursache der Pause
|
|
nicht aus ihrer Dauer allein bestimmen.
|
|
|
|
## SELinux: rsync-Zugriff verweigert (Exit 23)
|
|
|
|
Der Gemini-Lauf vom 10.09.2026 um 14:58 Uhr scheiterte nach drei erfolgreichen
|
|
DB-Dumps beim Kopieren von `/var/www/html`. Das Audit bestätigt rsync im Kontext
|
|
`rsync_t`: Lesen von `httpd_sys_content_t` sowie Attributänderungen und Relabeling
|
|
im Staging wurden verweigert. Zusätzlich wurden geerbte Sperrdeskriptoren beanstandet.
|
|
Die gestoppten Dienste wurden laut Journal wieder gestartet und Nextcloud verließ
|
|
den Wartungsmodus. Es entstand kein vollständiger neuer Sicherungssatz.
|
|
|
|
Das aktuelle Paket setzt für den Update-Auftrag und den installierten Backup-Dienst
|
|
`SELinuxContext=system_u:system_r:unconfined_service_t:s0` und startet beide über
|
|
`/bin/bash`. **Diese privilegierten Prozesse und ihre Kindprozesse laufen damit
|
|
ohne SELinux-Einschränkung.** SELinux bleibt systemweit aktiv; andere Dienste
|
|
behalten ihre bestehende Policy. Der Installer ändert keine globalen rsync-Booleans,
|
|
keine Quell-Labels und keine Quellberechtigungen. Ein nicht zugelassener Kontext
|
|
führt zu einem sichtbaren Startfehler.
|
|
|
|
Auf Gemini ist die Bash-Startkette mit diesem Kontext und erfolgreichem
|
|
rsync-Auflisten des Webverzeichnisses unter Enforcing geprüft. Der direkte
|
|
Unit-Start von `/usr/bin/rsync` scheiterte dagegen mit 203/EXEC und bildet die
|
|
Startkette des Pakets nicht ab. Manuelle Unit-Anpassungen sind nicht erforderlich:
|
|
das aktuelle Paket mit denselben Gitea-/Cron-/Mail-Optionen erneut starten.
|
|
|
|
Vor dem Wartungsmodus prüft das Paket über rsync die Quellverzeichnisse und die
|
|
Übernahme ihrer Verzeichnisattribute in einen privaten temporären Prüfbereich.
|
|
Dabei werden keine Dateiinhalte kopiert. Die Probe erfasst nicht jede untergeordnete
|
|
Datei; der vollständige Kopierlauf und die Remote-Prüfung bleiben erforderlich.
|
|
rsync erhält keine geerbten Sperrdeskriptoren; die Elternprozesse halten die Sperren
|
|
weiter. Der SELinux-Kontext des Backup-Prozesses erscheint im Protokoll.
|
|
|
|
Bei einem erneuten Fehler `update.log`, die ausgegebene Ergebnisdatei und die
|
|
passenden AVC-Meldungen prüfen. Maßgeblich für den erfolgreichen Abschluss bleibt
|
|
`SUCCESS` in `result.txt`; erst danach aktiviert der Installer den Backup-Timer.
|
|
Eine Wiederherstellungsprobe auf einem separaten System steht weiterhin aus.
|
|
|
|
## Erneuter Dienststart während der Sicherung
|
|
|
|
Am 10.09.2026 starteten auf Gemini um 15:15 Uhr Apache und PHP-FPM während der
|
|
Nextcloud-Datenkopie erneut. Paket `c0a24b63fc1c` hatte die SELinux-Zugriffe bereits
|
|
korrigiert, schützte jedoch nicht vor fremden Startaufträgen. Den betroffenen
|
|
Lauf nicht als konsistente Sicherung abnehmen, auch falls Upload/Hashprüfung
|
|
anschließend erfolgreich waren. Der konkrete Auslöser des Startauftrags ist
|
|
noch offen. Die 90 Sekunden Apache-Stopp sind dagegen durch dessen Journal
|
|
erklärt: Timeout beim Beenden, anschließend SIGKILL durch systemd. Das neue Paket
|
|
ändert weder Apache-Timeout noch seine Signalbehandlung pauschal.
|
|
|
|
Einen noch laufenden alten Update-Auftrag kontrolliert beenden:
|
|
|
|
```bash
|
|
sudo systemctl stop app-backup-upgrade.service
|
|
sudo journalctl --no-pager -u app-backup-upgrade.service -n 60
|
|
sudo systemctl --no-pager is-active httpd php-fpm gitea postfix dovecot crond
|
|
```
|
|
|
|
Im Protokoll die Wiederaufnahme und das Verlassen des Wartungsmodus prüfen.
|
|
Bei Fehlern die ausgegebene `recovery-*.json` beachten. Erst nach abgeschlossenem
|
|
alten Auftrag das aktuelle Paket mit den bisherigen Gitea-/Cron-/Mail-Optionen
|
|
starten. Bestehende Sicherungssätze und Arbeitsverzeichnisse nicht pauschal löschen.
|
|
|
|
Das neue Paket richtet für die Kopierphase vorübergehende systemd-Startbedingungen
|
|
ein und prüft Writer-Zustände sowie Aktivierungszeitpunkte vor/nach den Kopien.
|
|
Es entfernt beim Wiederanlauf nur eigene Ergänzungen; bei einem teilweise
|
|
ausgeführten Restore bleiben sie bis zur manuellen Prüfung bestehen. Einzelheiten
|
|
zur gezielten Freigabe stehen in `Dokumentation.md` bei der Wiederanlaufhilfe.
|
|
Die permanente Dienstkonfiguration und vorhandene Maskierungen bleiben erhalten.
|
|
Die Meldung `Copy window complete; writer guards verified` bestätigt das Ende
|
|
der geprüften Kopierphase. Abgeschlossen ist die Paketabnahme erst bei `SUCCESS`
|
|
in der Ergebnisdatei nach vollständiger Remote-Prüfung.
|
|
|
|
Der Abbruchpfad wurde ebenfalls korrigiert: Bisher erreichte TERM bei
|
|
`KillMode=mixed` zunächst nur den Update-Hauptprozess. Eine wartende Bash konnte
|
|
dadurch den Stop bis zum Ende ihres Backup-/Upload-Kindprozesses verzögern.
|
|
Die neuen Units verwenden `KillMode=control-group`; die Protokollprozesse bleiben
|
|
während der Fehlerbehandlung verfügbar. Nach einem Update-Abbruch das Journal
|
|
und die Dienstzustände prüfen; insbesondere ein Stop-Timeout ist kein Nachweis
|
|
für eine erfolgreiche Wiederaufnahme. Die Änderung wirkt für neue Aufträge,
|
|
nicht nachträglich für einen bereits gestarteten alten Worker.
|
|
|
|
## OneDrive: HTTP 409 resourceModified und stilles Journal
|
|
|
|
Der Lauf auf Gemini vom 10.09.2026 ab 15:30 Uhr hat die geschützte Kopierphase
|
|
und Dienstwiederaufnahme erfolgreich abgeschlossen. Um 15:46:11 meldete rclone
|
|
1.74.3 bei `wordpress.tar.zst` HTTP 409 `resourceModified`; das deutet auf einen
|
|
Versions-/eTag-Konflikt am OneDrive-Objekt. Der konkrete Auslöser ist anhand
|
|
dieser Meldung nicht bestimmt. Das später übermittelte Protokoll bestätigt:
|
|
Der erste Kopierversuch endete um 15:56:33 mit einem Fehler, der zweite war um
|
|
15:58:03 erfolgreich. Die Rückleseprüfung meldete um 15:59:37 `0 differences found`
|
|
und `15 matching files`. Danach bestand die separate Remote-Restore-Prüfung
|
|
für 14 Archive, gefolgt von `SUCCESS` und `Backup-Timer aktiv.`
|
|
Der Satz `appbackup_2026-09-10_13-30-17_ff95c1ac` hat damit die technische
|
|
Paketabnahme bestanden. Das zuvor gelesene `RUNNING` stammte aus der noch
|
|
laufenden Prüfung. Auch die mit `ERROR` protokollierte Zeile
|
|
`Attempt 2/6 succeeded` beschreibt einen erfolgreichen Wiederholungsversuch.
|
|
Eine erneute Installation allein wegen dieses überwundenen Konflikts ist nicht nötig.
|
|
|
|
HTTP 409 ist in dieser rclone-Version nicht in der allgemeinen Liste unmittelbar
|
|
wiederholter OneDrive-HTTP-Fehler enthalten. `--low-level-retries 20` bedeutet daher
|
|
nicht, dass genau dieser Fehler sofort 20-mal versucht wird. Die standardmäßig
|
|
bis zu sechs Versuche über `--retries` betreffen den übergeordneten Kopierauftrag;
|
|
andere Dateiübertragungen können vor dessen Wiederholung noch laufen. Bei als
|
|
fatal oder nicht wiederholbar eingestuften Fehlern kann rclone früher abbrechen.
|
|
Quelle: [rclone 1.74.3 OneDrive-Code](https://github.com/rclone/rclone/blob/v1.74.3/backend/onedrive/onedrive.go),
|
|
[Wiederholungen](https://rclone.org/docs/#retries-int).
|
|
|
|
Die bisherigen Aufträge zeigten normale Fortschrittsstatistiken nicht an:
|
|
rclone meldet sie standardmäßig auf INFO, die normale Logschwelle ist NOTICE.
|
|
Das aktuelle Paket setzt `--stats-log-level NOTICE --stats-one-line` mit
|
|
`RCLONE_STATS_INTERVAL="1m"` und meldet die Phasen Upload, Remote-Dateiprüfung und
|
|
Freigabe des Abschlussmarkers. Statistiken gehen nach stderr, damit maschinell
|
|
gelesene Marker und Dateilisten auf stdout unverändert bleiben.
|
|
Quelle: [rclone-Statistiken](https://rclone.org/docs/#stats-log-level-loglevel).
|
|
|
|
`RCLONE_TIMEOUT="1h"` ist die bestehende I/O-Leerlauffrist, keine Gesamtlaufzeit
|
|
und kein Versprechen einer Meldung pro Minute. `RUNNING` und der systemd-Zustand
|
|
`activating/start` bei der oneshot-Unit belegen keinen Datenfortschritt. Bei einem
|
|
stillen alten Auftrag Prozesszustand und TCP-Zähler mit `ps`/`ss` prüfen;
|
|
steigende Zähler belegen Netzwerkverkehr, aber noch keinen erfolgreichen Upload.
|
|
Quelle: [I/O-Leerlauffrist](https://rclone.org/docs/#timeout-duration).
|
|
|
|
Eine neue Paketdatei oder geänderte Config ergänzt keine Statistiken im bereits
|
|
laufenden rclone-Prozess. Keinen zweiten Upload parallel starten und den
|
|
vorhandenen lokalen Satz nicht löschen. Ein einzelner 409-Fehler begründet keine
|
|
Änderung der Upload-Optionen wie `--ignore-existing`. Seit 16.09.2026 wird
|
|
`--size-only` gezielt beim Metadatenvergleich eingesetzt. Entscheidend sind lokale
|
|
Manifest-/Archivprüfung, erfolgreicher Upload mit Remote-Dateiprüfung und
|
|
`SUCCESS` in der Ergebnisdatei; der Monatslauf liefert den separaten Restore-Nachweis.
|
|
|
|
## Paket reproduzieren
|
|
|
|
Aus einem sauberen, eingecheckten Repository:
|
|
|
|
```bash
|
|
python3 tools/build-update-package.py
|
|
```
|
|
|
|
Ausgabe: `dist/app-backup-update-COMMIT.run` und zugehörige SHA-256-Datei.
|
|
Das Paket enthält nur explizit freigegebene Programm-/Dokumentationsdateien und
|
|
Credential-Vorlagen; keine Git-Historie, echten CNF-Dateien oder Backupdaten.
|
|
Die Prüfsumme schützt vor Übertragungsfehlern, ist keine digitale Signatur.
|
|
Das ausführbare Paket ausschließlich über euren vertrauenswürdigen Kanal beziehen.
|
|
|
|
## Verifikation der Lieferung
|
|
|
|
Aktueller Stand vom 15.09.2026 für das Code-Paket `3730ab4676a5`: 119 Fälle im
|
|
Standardlauf, 111 erfolgreich und acht planmäßig übersprungen; die drei echten
|
|
Benutzer-systemd-Fälle bestanden separat. Fünf optionale Docker-Integrationstests
|
|
wurden bei diesem abschließenden Lauf nicht erneut ausgeführt. ShellCheck und
|
|
Shell-Syntaxprüfung bestanden. Details stehen im
|
|
[Nachtrag zur Stop-Korrektur](#nachtrag-vom-15092026-healthcheck-verdrängt-apache-stop).
|
|
|
|
Verifikation am 12.09.2026: Standardlauf mit 81 Fällen erfolgreich (80 bestanden, ein separater Docker-Test planmäßig übersprungen; 704,8 Sekunden). Zusätzlich bestanden alle 19 gezielten Restore-Tests mit echten DB-Containern und der Installer-/Rollback-Test mit aktiviertem Restore-Timer. Geprüft sind vollständiges Entpacken, isolierter SQL-Import, fehlerhafte Dumps, Platzgrenzen und Bereinigung nach normalen und harten Abbrüchen. ShellCheck, Shell-Syntax und systemd-Unit-Prüfung erfolgreich. Echte E-Mails werden in Entwicklungstests nicht versendet; die Serverabnahme des Monatslaufs erfolgt nach Installation.
|
|
|
|
Die Tests enthalten echte MariaDB-Dumps/Imports und lokale rclone-Crypt-Roundtrips;
|
|
systemd/occ und die systemd-run-Übergabe sind simuliert. Das Übergabemodell
|
|
berücksichtigt jetzt das Warten auf den oneshot-Startauftrag: Der Regressionstest
|
|
scheiterte mit dem alten Code und war nach dem Fix erfolgreich. Geprüft sind auch
|
|
abgewiesene Übergaben, eingereihte Worker trotz fehlgeschlagener Antwort und
|
|
persistente Fehlerprotokolle bei belegter Update-Sperre. Die tatsächliche
|
|
SELinux-Durchsetzung wird im Debian-Testcontainer nicht nachgebildet; der erfolgreiche
|
|
Bash-/rsync-Lesetest auf Gemini wurde separat vom Betreiber durchgeführt. Die vollständige
|
|
Server-/OneDrive-Prüfung erfolgt beim Paketlauf. Ein fachlicher Restore
|
|
auf einem separaten Testsystem bleibt erforderlich.
|
|
|
|
Die neuen Tests bilden fremde Startaufträge während rsync, zwischenzeitliche
|
|
Neustarts, bestehende Maskierungen und Fehler bei der Sperrfreigabe ab. Die
|
|
Condition-Auswertung (Sperrverzeichnis vorhanden/entfernt) und Unit-Syntax wurden
|
|
zusätzlich mit echtem `systemd-analyze` geprüft. Der tatsächliche systemd-Manager
|
|
und SELinux auf Gemini wurden anschließend im vom Betreiber ausgeführten
|
|
Paketlauf mit geschützter Kopie und erfolgreichem Abschluss geprüft. Die fachliche
|
|
Wiederherstellung auf einem separaten Testsystem bleibt offen.
|