feat(updater): support updates after verified SeaweedFS migration

This commit is contained in:
2026-09-28 15:47:06 +02:00
parent 790f20b499
commit 2b947c5e8f
20 changed files with 1074 additions and 67 deletions

View File

@@ -27,19 +27,20 @@ Die fachliche Abnahme erfolgt zusätzlich auf der konkreten Instanz.
und die unveränderte Anwendung wieder starten.
**Der Pilot ist noch kein neuer Standardinstaller und kein reguläres
FEDEO-Release.** Der bisherige Anwendungs-Updater kennt nur MinIO. Seine Aufträge
bleiben nach der Umstellung bewusst über `recoveryRequired` gesperrt, bis ein
getesteter Provider-Adapter installiert wird. Diesen Zustand nicht mit dem alten
FEDEO-Release.** Ältere Anwendungs-Updater kennen nur MinIO. Ihre Aufträge
bleiben nach der Umstellung bewusst über `recoveryRequired` gesperrt. Dieser
Entwicklungsstand enthält den SeaweedFS-Adapter und eine ausdrücklich geprüfte
Übergabe über `adopt-updater` (unten). Diesen Zustand nicht mit dem alten
`resolve` oder durch Löschen der Statusdatei aufheben. Ein alter Installer oder
ein altes Release-Compose darf die umgestellte Installation nicht überschreiben.
FEDEO 3.3.0 kann im Systemstatus weiterhin den MinIO-spezifischen Health-Endpunkt
abfragen und dadurch den Dateispeicher als gestört anzeigen. Die tatsächliche
Funktionsprüfung erfolgt im Pilot über signierte S3-Operationen. Herstellerneutrale
Oberflächenchecks, eine Migrationskarte in der Oberfläche, automatische Updates
auf SeaweedFS und der Standardinstaller sind nachfolgende Arbeitspakete.
Wer diese Einschränkungen noch nicht im Betrieb tragen möchte, führt zunächst
nur die Vorprüfung durch und bleibt mit der Instanz auf MinIO.
Funktionsprüfung erfolgt im Pilot über signierte S3-Operationen. Dieser
Entwicklungsstand prüft den angemeldeten S3-Bucket auch im Systemstatus; dafür
ist anschließend ein Anwendungsrelease mit dieser Änderung erforderlich.
Der Speicherwechsel selbst bleibt eine eigene betreute Hostaktion. Der bisherige
Standardinstaller wird durch die Migration nicht ersetzt.
### Warum das Pilotimage eine gezielte Korrektur enthält
@@ -230,6 +231,47 @@ demselben Host anschließend auf das vorgesehene externe Backupziel übernehmen.
MinIO-Daten, alte Container, Test-Restores und Offline-Images werden vom Pilot
nicht automatisch gelöscht.
## An den regulären Updater übergeben
Erst nach `phase: complete`, erfolgreicher Anmeldung und fachlicher Prüfung eines
bestehenden Dokuments ausführen. Die Übergabe stoppt keine FEDEO-Container:
```sh
sudo python3 pilot.py adopt-updater --directory /opt/fedeo
sudo python3 /usr/local/lib/fedeo-updater/selfhost-update.py check --directory /opt/fedeo
```
Das neu erstellte Paket enthält die vier zusammengehörigen Updater-Dienstdateien
mit Prüfsummen. `adopt-updater` installiert zuerst diesen Host-Dienst und ruft
danach `adopt-storage` auf. Damit wird die alte Sperre erst nach Installation des
passenden Updaters freigegeben. Bereits ausgegebene Pilotarchive bleiben unverändert;
für eine schon umgestellte Instanz ein neues geprüftes Paket bereitstellen.
**Dort nur `adopt-updater` ausführen, nicht erneut planen, kopieren oder aktivieren.**
Für diese reine Übergabe ist kein erneutes Laden der Images erforderlich.
Die Übernahme verlangt den abgeschlossenen Migrationszustand einschließlich
Schreibfreigabe, vollständigem Kopiernachweis, erfolgreicher S3-Abnahmen und
prüfsummengleicher Restore-Sicherung. Compose und `.env` müssen dem Pilotstand
entsprechen. Sie prüft außerdem die tatsächlich laufenden Anwendungsimages,
SeaweedFS-Image, lokale Mounts, Konfigurationsdateien und internen S3-Alias sowie
das gestoppte und getrennte ursprüngliche MinIO. Ein aktueller Lesezugriff erfolgt
mit dem installierten Backend-SDK. Fehler lassen die Updatesperre bestehen.
Danach sind `check` und `apply` über den Host-Dienst und die bestehende Oberfläche
möglich. Der erste Prüfplan benötigt keine pauschale Compose-Übernahmefreigabe.
Der Adapter erhält SeaweedFS samt Konfiguration, Datenpfaden, Zugangsdaten und
dem während der Migration festgehaltenen PostgreSQL-Image. Er entfernt die alten
MinIO-Dienste aus dem heruntergeladenen Release-Compose, bevor Images geladen
werden. Ein Anwendungsupdate lädt oder startet daher weder MinIO noch `mc`.
Ein Wechsel der SeaweedFS- oder PostgreSQL-Version ist ein separater Vorgang.
Vor jeder Datenbankschemamigration prüft das **Zielbackend-SDK** Schreiben,
Lesen, MIME-Erhalt, Streaming, signierte Links, anonymen Zugriffsschutz und
Löschen am aktiven Speicher. Ein Fehler hält die Anwendung angehalten und
bewahrt den Wiederherstellungszustand. Die normale Anwendungsupdatesicherung
enthält `storage/`, die Speicherbeschreibung und das exakte SeaweedFS-Image.
Wiederherstellung und Grenzen stehen in [Selfhost-Updates](selfhost-updates.md).
## Nachgewiesene Tests und ausstehende Freigaben
Der lokale S3-Test verwendet das offizielle MinIO-Release-Binary vom 7. September
@@ -249,7 +291,10 @@ Die Host-Integrationstests verwenden echte Speicher- und PostgreSQL-Container,
aber künstliche Anwendungsprozesse. Rückkehr vor Schreibfreigabe sowie vollständige
Umschaltung mit Restore und gesperrter Rückkehr nach Schreibfreigabe wurden erfolgreich
durchlaufen. Die fachliche Abnahme von FEDEO auf der
konkreten Instanz, ein physischer Hostneustart während jeder Phase, das reguläre
Anwendungsupdate auf SeaweedFS und die vollständige Wiederherstellung auf einem
anderen Host sind damit noch nicht nachgewiesen. Deshalb bleibt dieser Stand ein
konkreten Instanz, ein physischer Hostneustart während jeder Phase und die
vollständige Wiederherstellung auf einem anderen Host sind damit noch nicht
nachgewiesen. Der zusätzliche Test `scripts/update/tests/host_storage_integration.py`
prüft Migration, Updater-Übernahme, zwei Anwendungsupdates und Wiederherstellung
aus einer regulären Updatesicherung mit echten Speicher-/Datenbankcontainern
und künstlichen Anwendungsimages. Deshalb bleibt der Speicherwechsel ein
betreuter Pilot; die allgemeinen Freigabekriterien des Konzepts gelten weiter.

View File

@@ -6,20 +6,75 @@
- Linux/amd64, Python ab 3.10, Docker Compose ab 2.24, `tar` und `du`.
- Bestehendes Betriebsverzeichnis, standardmäßig `/opt/fedeo`, mit `.env` und `docker-compose.yml`; kein Git-Checkout.
- Standard-Stack mit `traefik`, `db`, `minio`, `createbuckets`, `backend`, `frontend` und `node-exporter`. PostgreSQL und MinIO verwenden die lokalen Verzeichnisse `postgres/` und `minio/`.
- Standard-Stack mit `traefik`, `db`, `minio`, `createbuckets`, `backend`, `frontend` und `node-exporter`. PostgreSQL und MinIO verwenden die lokalen Verzeichnisse `postgres/` und `minio/`. Nach geprüfter Pilotübernahme ersetzt `objectstore` (SeaweedFS) die beiden MinIO-Dienste; dessen Daten liegen unter `storage/`.
- Als root auf dem Server ausführen: Docker-Zugriff und Leserechte für die Daten- und Zertifikatsverzeichnisse werden benötigt. Ein entfernter Docker-Daemon wird abgewiesen.
- Die öffentliche HTTPS-Adresse muss vom Host erreichbar sein und ein gültiges Zertifikat haben.
- Eine Wartungsunterbrechung für alle Mandanten einplanen. Vor dem Backup werden alle laufenden Dienste außer PostgreSQL angehalten, auch der öffentliche Proxy und alle im Backend laufenden Hintergrundaufgaben. Eine separate Wartungsseite folgt mit der späteren Oberflächenintegration.
Der Updater verweigert externe Datenbanken, externen S3-/Seafile-Speicher, zusätzliche Dienste, Compose-Profile, geänderte Datenpfade und PostgreSQL-Imagewechsel. Dafür braucht es zunächst passende Backup-/Migrationsadapter. Eigene Einstellungen innerhalb der unterstützten Dienste können in `docker-compose.override.yml` **oder** `docker-compose.override.yaml` bleiben; der Updater verwendet diese Datei bei jedem Compose-Aufruf. Änderungen an dieser Override-Datei werden nicht überschrieben.
Eine gezielte Ausnahme ist die Stilllegung des **entfernten alten Matrix-Stacks**: `matrix-db`, `matrix-synapse`, `matrix-redis`, `matrix-element`, `matrix-livekit`, `matrix-rtc-jwt`, `matrix-turn` und `matrix-well-known` dürfen in der bestehenden Konfiguration vorkommen. Die Zielkonfiguration muss ausschließlich die sieben FEDEO-Dienste enthalten, auch nach Zusammenführung mit einer Override-Datei. Matrix wird nicht in den neuen Stack übernommen. Andere Zusatzdienste bleiben gesperrt; die Fehlermeldung nennt die konkreten Abweichungen. Ein Abbruch mit `mutationStarted: false` und `recoveryRequired: false` benötigt keine Wiederherstellung und keinen `resolve`-Aufruf.
Eine gezielte Ausnahme ist die Stilllegung des **entfernten alten Matrix-Stacks**: `matrix-db`, `matrix-synapse`, `matrix-redis`, `matrix-element`, `matrix-livekit`, `matrix-rtc-jwt`, `matrix-turn` und `matrix-well-known` dürfen in der bestehenden Konfiguration vorkommen. Die Zielkonfiguration muss ausschließlich die FEDEO-Dienste des jeweiligen Speicherproviders enthalten, auch nach Zusammenführung mit einer Override-Datei. Matrix wird nicht in den neuen Stack übernommen. Bereits stillgelegte Matrix-Container bleiben erhalten und ihre lokalen Bind-Verzeichnisse werden weiter gesichert. Andere Zusatzdienste bleiben gesperrt; die Fehlermeldung nennt die konkreten Abweichungen. Ein Abbruch mit `mutationStarted: false` und `recoveryRequired: false` benötigt keine Wiederherstellung und keinen `resolve`-Aufruf.
Für diesen Übergang müssen die Matrix-Daten lokal unter `matrix/` liegen, insbesondere `matrix/postgres` und `matrix/synapse`; symbolische Links, andere konfigurierte Datenpfade, benannte Volumes und spezielle Compose-Konfigurationen benötigen eine manuelle Stilllegung. Die tatsächlichen Bind-Mounts der alten Container müssen zur Compose-Datei passen. Der Plan nennt `retiredServices` und `retainedDataPaths` und berücksichtigt den zusätzlichen Backup-Platz. Alle Matrix-Container werden vor dem Backup gestoppt. Das komplette lokale `matrix/`-Verzeichnis wird bei gestoppter Matrix-Datenbank in `files.tar` gesichert. Erst nach erfolgreichem Backup setzt der Updater die Neustartrichtlinie der alten Matrix-Container auf `no`, damit sie auch nach einem Host-Neustart stillgelegt bleiben. Er löscht weder diese Container noch ihre Daten oder Volumes. Image-seitig angelegte anonyme Volumes und schreibbare Container-Schichten bleiben an den alten Containern erhalten; sie sind nicht Bestandteil von `files.tar`. Die alten Container daher für die Wiederherstellung behalten und nicht mit `--remove-orphans` oder einem Docker-Prune entfernen.
Die Stilllegung vor der Dateisicherung entspricht den Anforderungen an ein [PostgreSQL-Dateisystem-Backup](https://www.postgresql.org/docs/16/backup-file.html); die Container-Richtlinie wird mit [Docker `update --restart`](https://docs.docker.com/reference/cli/docker/container/update/) geändert.
Die Zielversion muss bereits die festen MinIO-Digests und die neuen Backend-/Frontend-Healthchecks enthalten. Ältere Releases bleiben über den in `docs/releases.md` beschriebenen manuellen Ablauf installierbar. Ein Versionswechsel des Betriebssystems oder der Docker Engine gehört nicht zu diesem Ablauf.
Die Zielversion muss die Backend-/Frontend-Healthchecks enthalten; bei weiterhin aktivem MinIO zusätzlich feste MinIO-/mc-Digests. Ältere Releases bleiben über den in `docs/releases.md` beschriebenen manuellen Ablauf installierbar. Ein Versionswechsel des Betriebssystems oder der Docker Engine gehört nicht zu diesem Ablauf.
## Bereits auf SeaweedFS umgestellte Instanzen
Speicherumstellung und Anwendungsupdate bleiben getrennte Wartungsschritte.
Für weitere Installer-Instanzen zuerst den [Migrationsablauf](minio-umstellung-pilot.md)
mit Kopie, vollständiger Prüfung und echtem Restore durchführen. Er verwendet
die vorhandenen MinIO-Images und benötigt keinen funktionierenden MinIO-Download.
Der normale `apply`-Befehl startet keine verdeckte Speichermigration.
Der neue Standardinstaller und Setup-Assistent erkennen vorbereitete bzw.
durchgeführte Speicherumstellungen und verweigern dort das Überschreiben der
Konfiguration oder ein pauschales Entfernen des Stacks. Alte Skriptstände besitzen
diesen Schutz nicht und dürfen auf umgestellten Instanzen nicht mehr ausgeführt werden.
Nach Installation der **vier zusammengehörigen neuen Host-Dienstdateien** übernimmt
der neue Updater einen vollständig abgeschlossenen Pilot:
```sh
sudo python3 /usr/local/lib/fedeo-updater/selfhost-update.py adopt-storage --directory /opt/fedeo
sudo python3 /usr/local/lib/fedeo-updater/selfhost-update.py check --directory /opt/fedeo
```
Das neue Pilotpaket verbindet Dienstinstallation und Übernahme als `pilot.py
adopt-updater`. Die Übernahme verändert keine Anwendungsimages und stoppt keine
FEDEO-Dienste. Sie prüft Migrations-/Restore-Nachweise, Originalzustand der
Anwendung, aktiven Speicher und S3-Lesezugriff und schreibt erst dann
`.updates/storage-provider.json`. Die alte Sperre wird als letzter Schritt
freigegeben. Bei Abbruch kann derselbe Befehl wiederholt werden. `resolve`
verweigert ausdrücklich die Freigabe einer Speichermigration.
Bei Installation aus dem Pilotpaket die CLI unter `/usr/local/lib/fedeo-updater/`
verwenden. Eventuell noch vorhandene ältere Kopien unter `/opt/fedeo/scripts/`
werden durch die Dienstinstallation nicht ersetzt.
Weitere Anwendungsupdates erzeugen das Release-Compose mit dem übernommenen
SeaweedFS-Dienst. Image, Mounts, Startkonfiguration, interner Alias und Zugangsdaten
bleiben erhalten; MinIO und `mc` werden weder geladen noch gestartet. Das bei der
Pilotmigration festgehaltene PostgreSQL-Image bleibt ebenfalls erhalten. Eine
geänderte PostgreSQL-Referenz im Release blockiert die Anwendung bis zur separaten
Datenbankmigration. Ein Anwendungsupdate aktualisiert **nicht** die SeaweedFS-Version.
Das Backup enthält den Datenbankdump und die bei gestopptem SeaweedFS gesicherte
vollständige Ablage `storage/` in `files.tar`, zusätzlich `storage-image.tar` und
`config/.updates/storage-provider.json`. Der Platzbedarf berücksichtigt das Image.
Vor den SQL-Migrationen wird das neue Backendimage mit seinem tatsächlichen SDK
gegen S3 geprüft (PUT/HEAD/GET/DELETE, Streaming, MIME, 24-Stunden-Signatur und
anonymer Zugriffsschutz). Ein unterbrochener Test protokolliert seinen eindeutigen
Prüfschlüssel; `resolve` bereinigt ausschließlich diesen mit passender Prüfmetadatenmarkierung,
nachdem zurückgebliebene Prüfcontainer entfernt wurden und die Anwendung wieder
erreichbar ist. Unbekannte Dateien werden nicht gelöscht.
Die Oberfläche neuer FEDEO-Releases zeigt den erkannten Speicher im Updateplan
und unterscheidet die ausstehende Speicherübergabe von einem fehlgeschlagenen
Anwendungsupdate. Ältere Backends können den neuen Host-Dienst weiterhin nutzen;
zusätzliche Planinformationen werden dort ausgeblendet. Nach einem Apprelease
mit dem neuen Systemstatus ersetzt ein authentifizierter S3-Bucket-Check den
MinIO-spezifischen Health-Endpunkt.
## Bereitstellung
@@ -162,7 +217,7 @@ Aufträge liegen dauerhaft und root-lesbar unter `.updates/service/`. Nach einem
3. Aktuelle und neue Compose-Konfiguration mit Docker Compose validieren. Projektname, Container-Identitäten, Mounts, Netzwerke und Zugangsdaten erhalten. Die Shell-Umgebung überschreibt dabei keine Werte aus der Instanz-`.env`.
4. Speicherplatz prüfen: mindestens 5 GiB frei am Docker-Datenverzeichnis vor dem Pull sowie geschätzte Backup-Größe plus Reserve im Betriebsverzeichnis. Images mit exakt gepinntem SHA-256-Digest nur laden, wenn sie lokal fehlen (`pull --policy missing`); vorhandene Tags ohne passenden Digest reichen dafür nicht aus. Bewegliche Infrastruktur-Tags weiterhin aktualisieren (`pull --policy always`). Ein fehlendes, nicht herunterladbares Image beendet den Auftrag vor der Wartung. Backup-Platz erneut prüfen. Während der anschließenden Infrastrukturstarts und Migrationen erfolgt kein weiterer Pull (`up`/`run --pull never`), auch nicht bei einer abweichenden Pull-Policy in einer Override-Datei.
5. Schreibende Dienste und Proxy anhalten. PostgreSQL bleibt für `pg_dump` aktiv.
6. Konfiguration, Container-Metadaten, PostgreSQL-Dump im Custom-Format, globale PostgreSQL-Rollen, gestoppten MinIO-Dateispeicher und Zertifikate sichern. Dump und TAR auf Lesbarkeit prüfen und SHA-256-Prüfsummen schreiben. `backup/complete.json` markiert ein vollständig geschriebenes Backup; ein Restore-Probelauf auf einer getrennten Instanz wird dadurch nicht ersetzt.
6. Konfiguration, Container-Metadaten, PostgreSQL-Dump im Custom-Format, globale PostgreSQL-Rollen, den gestoppten Dateispeicher und Zertifikate sichern. Bei SeaweedFS gehören dessen vollständige Ablage, Konfiguration und Image dazu. Dump und TAR auf Lesbarkeit prüfen und SHA-256-Prüfsummen schreiben. `backup/complete.json` markiert ein vollständig geschriebenes Backup; ein Restore-Probelauf auf einer getrennten Instanz wird dadurch nicht ersetzt.
Beim Übergang vom alten Matrix-Stack enthält das TAR zusätzlich `matrix/`. Container-Metadaten enthalten die ursprünglichen Image-IDs, Mounts und Neustartrichtlinien; `complete.json` nennt die stillgelegten Dienste und erhaltenen Container. Vor dem Dateiaustausch wird deren automatischer Neustart deaktiviert. Das Zielrelease enthält keine Matrix-Dienste und keine Backend-Abhängigkeit auf Synapse mehr.
7. Compose-Datei und `.env` einzeln atomar ersetzen. In `.env` wird ausschließlich `FEDEO_VERSION` verändert; `.env.example` und Setup-Skript werden erneuert. Den laufenden Updater ersetzt dieser Vorgang nicht.
8. Infrastruktur starten, Bucket-Einrichtung ausführen und Migrationen explizit in einem benannten Einmalcontainer starten. Beim anschließenden regulären Backend-Start läuft dessen bestehende Migrationsprüfung nochmals; bereits angewendete Migrationen werden dabei übersprungen.
@@ -185,7 +240,7 @@ Für die Rückkehr zum alten Stand in einem geplanten Wartungsfenster:
1. Alle schreibenden Dienste und den Proxy angehalten lassen; keinen neuen Update-Auftrag starten.
2. Prüfsummen aus `backup/complete.json` prüfen. Ursprüngliche Compose-Datei, `.env` und gegebenenfalls Override aus `backup/config/` wiederherstellen. `backup/containers.json` dokumentiert die ursprünglichen Image-IDs; insbesondere bewegliche Infrastruktur-Tags vor dem Start auf die gesicherten Image-Stände festlegen.
3. Falls Migrationen/Infrastrukturänderungen bereits begonnen haben: PostgreSQL und Dateispeicher aus dem **zusammengehörigen** Backup wiederherstellen. Der PostgreSQL-Dump ist für `pg_restore` geeignet; `globals.sql` enthält Rollen und Kennwörter und muss beim Wiederaufbau der Datenbank berücksichtigt werden. MinIO und Zertifikate bei gestoppten Diensten aus `files.tar` wiederherstellen. Die konkrete Rücksicherung bestehender Daten erfolgt bewusst manuell und ersetzt Daten.
3. Falls Migrationen/Infrastrukturänderungen bereits begonnen haben: PostgreSQL und Dateispeicher aus dem **zusammengehörigen** Backup wiederherstellen. Der PostgreSQL-Dump ist für `pg_restore` geeignet; `globals.sql` enthält Rollen und Kennwörter und muss beim Wiederaufbau der Datenbank berücksichtigt werden. MinIO bzw. die vollständige SeaweedFS-Ablage `storage/` und Zertifikate bei gestoppten Diensten aus `files.tar` wiederherstellen. Bei SeaweedFS auch die Speicherbeschreibung aus `backup/config/.updates/storage-provider.json` zurückspielen und das gesicherte Image mit `docker image load -i backup/storage-image.tar` laden. Die konkrete Rücksicherung bestehender Daten erfolgt bewusst manuell und ersetzt Daten. Der vor der Speicherumstellung erhaltene MinIO-Bestand gehört nicht zu einem aktuellen Anwendungsbackup; ihn keinesfalls als Abkürzung reaktivieren.
4. Wiederhergestellten Stack mit dessen Compose-Dateien starten und Funktionen prüfen. Alternativ den Fehler der Zielversion beheben und diese erfolgreich starten.
5. Erst nach erfolgreicher Wiederherstellung die Sperre aufheben:
@@ -202,8 +257,15 @@ Bei Rückkehr zum alten Matrix-Stack dessen ursprüngliche Compose-Datei aus dem
```bash
npm test
npm run commits:check
cd backend && node --import tsx --test tests/selfhostUpdates.test.ts
cd backend && node --import tsx --test tests/selfhostUpdates.test.ts tests/systemStatusStorage.test.ts
cd ../frontend && node --test tests/selfhost-updates.test.cjs
```
Die Update-Tests verwenden den echten Compose-Parser und einen simulierten Docker-Daemon. Sie prüfen u. a. Erfolg, Prüfsummen, Release-Auswahl, unveränderte Konfiguration, Speicherplatz, parallele Aufträge, Backupfehler, Migrationsfehler, falsche laufende Versionen und unterbrochene Aufträge. Die Matrix-Tests prüfen Stilllegung, Daten-/Container-Erhalt, Backup vor Änderung der Neustartrichtlinien, Fehler und Unterbrechungen sowie die weitere Ablehnung unbekannter Dienste. Ein vollständiger Test mit realem PostgreSQL-/MinIO-/Matrix-Restore auf einer separaten Selfhost-Testinstanz ist vor dem Produktionseinsatz zusätzlich erforderlich.
`python3 -B scripts/update/tests/host_storage_integration.py` prüft zusätzlich
MinIO-Migration, Speicherübernahme, zwei Anwendungsupdates und Restore der
regulären SeaweedFS-Updatesicherung mit echten Docker-Containern. Anwendung und
Release-/HTTP-Antworten sind isolierte Testdaten. Benötigte Images und Aufbau
stehen in `scripts/storage/README.md`. Die fachliche Abnahme des veröffentlichten
FEDEO-Releases auf einer Testinstanz bleibt zusätzlich erforderlich.