Files
app-backup/UPDATE_ANLEITUNG.md
T

800 lines
46 KiB
Markdown

# Automatisches Update-Paket
## 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.