Wiederherstellungsbereitschaft
Libre WebUI bietet als erste Sicherungsbarriere ein schreibgeschütztes Inventar. Es meldet bekannten Zustand und
Blockaden, sperrt aber keine Wartung und kopiert, verschlüsselt, lädt, löscht, repariert oder restauriert nichts.
Der Befehl libre-webui recovery-check führt diese recovery-check-Prüfung aus und erfasst dabei auch historische plugins-Verzeichnisse.
libre-webui recovery-check --json > recovery-inventory.json
Aus dem Quellcode einmal npm run build:backend ausführen und npm run recovery:check -- verwenden. npx/Homebrew
prüfen ~/.libre-webui; DATA_DIR oder explizite Pfade ersetzen dies.
Exit 0 ohne Blocker, 1 mit Blockern, 2 bei Argument-/Sammlungsfehler. Die Optionen --data-dir und --database werden als --data-dir PATH oder --database PATH
prüfen andere Orte. Standard akzeptiert nur reguläres, nicht verlinktes DATA_DIR/data.sqlite samt WAL/SHM. Eine
explizite Datenbank darf außerhalb liegen, bleibt aber regulär; ohne data-dir wird ihr Elternordner Datenwurzel.
Historische Plugindefinitionen aus dem Backend-Paket und relativen Altpfaden werden ebenfalls erfasst. Eigene Definitionen
blockieren reine Volume-Snapshots. Paketdeployments können --legacy-plugins-dir PATH mehrfach angeben.
docker exec libre-webui \
libre-webui recovery-check --json --data-dir /app/backend/data
Prüfungen des Inventars
Der versionierte Bericht enthält Versionen, SQLite-/WAL-/SHM-Größen, quick_check, Fremdschlüssel, Schemafingerabdruck,
fehlende Tabellen und No-follow-Validierung; Les-/Schreibbarkeit, Dateien und Bytes; Schlüsselquelle und irreversible
16-Zeichen-Fingerprint; .encryption_key-Prüfung; Plugins, Blobs, Medien, Stimmen, Dokumenttext, alte und Plattformvektoren
mit ACL; begrenzte Authentifizierung aller Blob-/Vektorumschläge und Schlüssel; erkennbare AES-GCM-Umschläge in Chats,
Notizen, Dokumenten, Präferenzen, Secrets, Galerie und E-Mail sowie AAD-gebundene Stimmen; Work-Aufgaben, Läufe, Vorschauen,
Docker-Volumes/PVCs/Hostidentitäten mit Label und exakter Aufgaben-ID; Medien- und dauerhafte Jobs, Versuche, Streams,
Ereignisse und Cursor; verschlüsselte Nutzlasten und syntaktisch begrenzte opaque Referenzen; Blocker, Warnungen und externen Zustand.
Schlüssel, JWT, Anbieterzugänge, Inhalte und Hostpfade werden nie ausgegeben. Ein Read-only-Mount warnt nur; starte die Anwendung nie gegen den Sicherungs-Snapshot.
Blocker
Blocker sind fehlende/defekte DB, unvollständiges Schema, Schlüsselkonflikt, beschädigter Ciphertext, überschrittene Grenzen, unlesbarer Pfad, verlinkte SQLite-Datei, aktive Work-/Medien-/Dauerjobs, fehlende/falsch gelabelte Workspaces, Ereignislücken, externe Plugins oder unverifizierbare Laufzeitressourcen. Stoppe Aktivität und behebe Ursachen; Bericht nicht ändern.
Dauerhafte Payloads werden identitätsgebunden als begrenztes kanonisches JSON authentifiziert. Opaque Referenzen werden nur
syntaktisch geprüft; referenceTargetsVerified bleibt false und Werte werden nie offengelegt.
Alter Klartext bleibt kompatibel, weil historische Textumschläge keinen Marker hatten. Kanonische Umschläge schlagen bei
Fehlform geschlossen fehl. Stimmen sind eindeutig an Profil/Eigentümer/Feld gebunden. encryption.legacyCiphertext meldet Summen.
Bei Schema v4 wird jedes users.email_lookup aus der authentifizierten E-Mail neu berechnet; fehlende, falsche oder zu null
gehörende Tokens blockieren. Vor-v4-Datenbanken besitzen die Spalte nicht.
Aktuelle Sicherungsgrenze
Der private Helfer stoppt die App und erstellt aus unveränderlichem Image, Volume und Umgebung ein integriertes Solo-Archiv.
Manifest Ed25519-signiert, Payload AES-256-GCM mit Operatorschlüssel. Enthalten sind SQLite, Blobs, Vektoren, Selektoren und
geschützte Konfiguration. Signatur, Checksum und entschlüsselte Payload werden geprüft. libre-webui-restore akzeptiert nur
ein neues Volume und veröffentlicht private Konfigurationsdateien.
Geschützt sind PostgreSQL-Pool-/Verbindungs-/Idle-/Statement-/Migrationstimeouts, Redis-Timeout, Blobquoten, Selektoren,
S3-Präfix und Adressierungsmodus; sie liegen verschlüsselt und werden als 0600 ausgegeben.
Nicht enthalten: Work-Volumes, PVCs, Hostordner, Ollama-Modelle und externer Anbieterzustand. Team nutzt offline PostgreSQL- Snapshot, exakt versionierte S3-Objekte, PGVector-Inventar, Konfiguration und Schlüsselidentität im selben Format; Redis wird aus SQL rekonstruiert.
Team authentifiziert Jobs/Ereignisse im Snapshot. Jeder Stream muss exakt 1..last_sequence enthalten, globaler Cursor darf
nicht zurückliegen. Restore wiederholt und vergleicht. Globale Cursorlücken sind wegen nichttransaktionaler Identity zulässig,
Streamsequenzen nicht.
Externes PLUGINS_DIR wird ausgeschlossen und blockiert bei Definitionen bis zur separaten Sicherung. Symbolische,
unregelmäßige oder unlesbare JSON-Dateien blockieren immer. Beide Profile bewahren dauerhafte SQL-Jobs; Solo hat integrierten,
Team externen Worker und Redis nur für Wake-up/Fan-out.
Produktionssecrets gehören in einen Manager, Archive verschlüsselt off-host und Restores in saubere Umgebung. Das Inventar ist Vorprüfung, kein Lock oder Beweis aller externen Ressourcen.
Signierte und verschlüsselte Sicherungsbefehle
Nutze globales libre-webui mit libre-webui backup, alternativ npx --yes libre-webui@latest; aus Source npm run recovery:backup --.
Das Image bietet /usr/local/bin/libre-webui. Team benötigt PostgreSQL-16-pg_dump/pg_restore.
Erzeuge den vom Betreiber verwahrten AES-256-GCM-Archivschlüssel und das Ed25519-Signierschlüsselpaar in einem privaten Verzeichnis. Verschiebe die privaten Schlüssel anschließend in einen geschützten Speicher außerhalb des Hosts:
install -d -m 0700 /absolute/private/libre-backup-keys
libre-webui backup keygen \
--directory /absolute/private/libre-backup-keys
libre-webui backup create \
--offline \
--data-dir /absolute/path/to/libre-data \
--output /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
libre-webui backup verify \
--archive /absolute/backups/libre-solo.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-preflight \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-apply \
--archive /absolute/backups/libre-solo.lwbackup \
--target /absolute/restore/libre-data \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-verify \
--target /absolute/restore/libre-data
Für Team alle Repliken/Worker stoppen und Quelle laden:
libre-webui backup create-team \
--offline \
--output /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-private-key /absolute/private/libre-backup-keys/backup-signing-private.pem
Leere PostgreSQL-DB und leeren versionierten S3-Bucket laden. Preflight prüft Leere; Apply restauriert, prüft PostgreSQL/S3/PGVector und schreibt private Konfiguration:
libre-webui backup restore-team-preflight \
--archive /absolute/backups/libre-team.lwbackup \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
libre-webui backup restore-team-apply \
--archive /absolute/backups/libre-team.lwbackup \
--configuration-output /absolute/restore/libre-team-config \
--encryption-key /absolute/private/libre-backup-keys/backup-encryption.key \
--signing-public-key /absolute/private/libre-backup-keys/backup-signing-public.pem
Richte eine Wiederherstellung niemals auf die Quelldatenbank, den Quell-Bucket,
ein bestehendes Datenverzeichnis oder ein Konfigurationsverzeichnis mit Dateien.
Bewahre den öffentlichen Signierschlüssel beim Wiederherstellungs-Runbook auf;
der Besitz von Archiv und öffentlichem Schlüssel allein kann die Nutzlast nicht
entschlüsseln. Behandle bei einem unvollständigen Rollback beide Ziele als
verunreinigt, bereinige PostgreSQL sowie alle S3-Versionen und Löschmarkierungen
im exakten Präfix und wiederhole restore-team-preflight.
Geplante verifizierte Wiederherstellungsübungen
Eine nie restaurierte Sicherung ist Hoffnung. Die Übung:
- Erstellt bei ruhigen Dauerjobs einen SQLite-Online-Snapshot und kopiert Dateien physisch.
- Erstellt mit temporären Schlüsseln ein signiertes AES-256-GCM-Archiv samt Inventar.
- Verifiziert und restauriert isoliert und prüft erneut.
- Misst Dauer als RTO und Abstand erfolgreicher Übungen als RPO-Grenze und löscht alles; sie ist keine Sicherung.
Aktiviere RECOVERY_DRILL_INTERVAL_HOURS (z. B. 24). Ein Koordinations-Lease verhindert Doppelstarts. System zeigt
Verlauf und „Jetzt ausführen“ über GET /api/recovery/drills und POST /api/recovery/drills/run. Unbeaufsichtigte Fehler
benachrichtigen alle Administratoren/Webhooks; manuelle melden Ablehnung direkt. RECOVERY_DRILL_HISTORY hält standardmäßig 60.
Übungen gelten für Solo/SQLite. Team behält backup create-team; dessen Probe bleibt ein Operator-Schritt.