Add three-scenario disaster recovery
This commit is contained in:
1 parent
e5e5d7fa4d
commit
bc2ca9af7d
18 files changed
+853
-107
No files matched your search
+185
-82
@@ -1,102 +1,205 @@
|
||||
# Backup und Wiederherstellung
|
||||
# Backup und vollständige Wiederherstellung
|
||||
|
||||
## Athena
|
||||
Athena besitzt zwei voneinander unabhängige Sicherungsebenen. Nur gemeinsam
|
||||
decken sie Systemplatten-, Datenplatten- und Totalausfall ab.
|
||||
|
||||
`mike-ai-backup` erzeugt alle fünf Stunden ein Archiv unter
|
||||
`/data/docker-backups` und behält 14 Tage. Gesichert werden:
|
||||
## Sicherungsebenen
|
||||
|
||||
- `/etc/mike-ai` mit lokaler Konfiguration,
|
||||
- Router-Zustand und erzeugte Bilder,
|
||||
- der kanonische Stack als zusätzlicher Snapshot.
|
||||
| Ebene | Ziel | Takt | Zweck |
|
||||
|---|---|---:|---|
|
||||
| Lokales Schnellbackup | `/data/docker-backups` | alle 5 Stunden | schneller Wiederaufbau, wenn nur die Systemplatte stirbt |
|
||||
| Verschlüsseltes Disaster-Backup | externes Restic-Repository, bevorzugt Unraid | nachts | Wiederaufbau, wenn `/data` oder beide Platten sterben |
|
||||
|
||||
Nicht in das Archiv gehören die großen Modellgewichte unter `/data/models`.
|
||||
Sie bleiben auf der Daten-SSD oder werden anhand der gepinnten Angaben in
|
||||
`config/install.env.example` erneut geladen. Die Dashboard-Historie liegt
|
||||
dauerhaft unter `/data/llama-dashboard`.
|
||||
Ein Backup, das ausschließlich auf `/data` liegt, schützt ausdrücklich nicht
|
||||
vor dem Ausfall der Datenplatte.
|
||||
|
||||
Für FLUX.2 Klein 9B müssen vor einem erneuten Download die Bedingungen der
|
||||
beiden Black-Forest-Labs-Repositories im Hugging-Face-Konto akzeptiert sein.
|
||||
Außerdem muss die in `HF_TOKEN_FILE` angegebene Token-Datei wiederhergestellt
|
||||
oder neu erzeugt werden. Der Token selbst ist absichtlich nicht Bestandteil
|
||||
des Git-Repositories oder des Athena-Backups.
|
||||
### Lokales Schnellbackup
|
||||
|
||||
Portainers lokale Konfiguration liegt im Docker-Volume `portainer_data` und
|
||||
wird zusammen mit den übrigen nicht reproduzierbaren Volumes gesichert und
|
||||
wiederhergestellt.
|
||||
`mike-ai-backup` sichert:
|
||||
|
||||
### Neuaufbau
|
||||
- `/etc/mike-ai`, einschließlich `install.env`, WireGuard und Geheimnissen,
|
||||
- ganz `/opt/mike-ai`, einschließlich aller bereitgestellten Spezialprojekte,
|
||||
- Router-Zustand und Router-Bilder,
|
||||
- Portainer-Daten.
|
||||
|
||||
1. Debian installieren und `/data` wieder am bisherigen Pfad einhängen.
|
||||
2. Dieses Repository klonen.
|
||||
3. Installationsdatei ausfüllen und Installation starten:
|
||||
Das Whisper-Volume ist reproduzierbar und wird bei Bedarf erneut geladen.
|
||||
Ein vorhandener Hugging-Face-Token wird als root-only
|
||||
`/etc/mike-ai/huggingface-token` mitgesichert, damit auch zugriffsbeschränkte
|
||||
FLUX-Gewichte nach einem Datenverlust automatisch erneut geladen werden
|
||||
können. Er steht niemals im Git-Repository.
|
||||
|
||||
### Externes Disaster-Backup
|
||||
|
||||
`athena-disaster-backup.timer` startet nachts ein verschlüsseltes,
|
||||
dedupliziertes Restic-Backup. Vor jedem Lauf erzeugt es ein konsistentes
|
||||
Docker-Schnellbackup und nimmt dieses in den externen Snapshot auf. Gesichert
|
||||
werden außerdem:
|
||||
|
||||
- `/etc/mike-ai` und `/opt/mike-ai`,
|
||||
- eigene Stimmen, Applio-Datasets und Trainingsstände unter `/data/voice`,
|
||||
- Musikprojekte und Ausgaben unter `/data/music`,
|
||||
- Audio-Trennungen unter `/data/audio`,
|
||||
- Dashboard-, Operator-, Benchmark- und Projektdaten.
|
||||
|
||||
Die rund 100 GB reproduzierbaren Modellgewichte unter `/data/models` werden
|
||||
nicht extern dupliziert. Kerngewichte lädt `install.sh` anhand URL und SHA256
|
||||
neu. Spezialmodelle laden ihre gepinnten Container beim ersten Start erneut.
|
||||
|
||||
### Herunterladbare Notfallpakete
|
||||
|
||||
Zusätzlich erzeugt `athena-export-backup.timer` alle fünf Stunden ein mit Age
|
||||
verschlüsseltes Komplettpaket der unersetzlichen Daten unter
|
||||
`/data/emergency-backups`. Das Dashboard zeigt die letzten fünf Generationen
|
||||
mit Größe, SHA256-Prüfsumme und einem fortsetzbaren Download an. Enthalten sind
|
||||
insbesondere Applio-Logs und -Checkpoints, Datasets, eigene Stimmen,
|
||||
Musikprojekte, Audioergebnisse, Konfiguration, Docker-Zustand und sämtliche
|
||||
bereitgestellten Quellstände. Erneut ladbare Modell- und Hugging-Face-Caches
|
||||
sind ausgeschlossen.
|
||||
|
||||
Bei aktuellem Datenbestand ist mit ungefähr 16 bis 20 GB je Generation zu
|
||||
rechnen. Fünf Generationen benötigen daher grob 80 bis 100 GB auf `/data`.
|
||||
Diese Pakete schützen nur dann vor einem Datenplattenausfall, wenn mindestens
|
||||
eine Generation tatsächlich auf einen anderen Rechner oder Datenträger
|
||||
heruntergeladen wurde. Die Pakete auf `/data` selbst sterben mit `/data`.
|
||||
|
||||
Der zu `recovery.age-recipient` gehörende private Age-Schlüssel darf nicht auf
|
||||
Athena verbleiben. Ohne ihn können die Pakete absichtlich nicht entschlüsselt
|
||||
werden.
|
||||
|
||||
## Einmalige Einrichtung des externen Backups
|
||||
|
||||
1. Ein physisch anderes Backupziel bereitstellen, vorzugsweise einen
|
||||
ausschließlich über WireGuard erreichbaren Unraid-Share, und zum Beispiel
|
||||
unter `/mnt/athena-offsite` einhängen.
|
||||
2. Eine starke Restic-Passphrase erzeugen und **zusätzlich außerhalb Athenas**
|
||||
in einem Passwortmanager oder auf einem Recovery-USB verwahren.
|
||||
3. Konfiguration anlegen:
|
||||
|
||||
```bash
|
||||
sudo ./install.sh --config /root/mike-ai-install.env
|
||||
cp config/disaster-backup.env.example /etc/mike-ai/disaster-backup.env
|
||||
chmod 600 /etc/mike-ai/disaster-backup.env
|
||||
# Repository, Mountpoint und Passwortdatei eintragen; danach:
|
||||
sed -i 's/^DISASTER_BACKUP_ENABLED=false/DISASTER_BACKUP_ENABLED=true/' \
|
||||
/etc/mike-ai/disaster-backup.env
|
||||
```
|
||||
|
||||
4. Letztes Datenarchiv einspielen:
|
||||
4. Ersten Lauf und Snapshot prüfen:
|
||||
|
||||
```bash
|
||||
sudo ./restore.sh --check /data/docker-backups/athena-latest.tar.gz
|
||||
sudo ./restore.sh /data/docker-backups/athena-latest.tar.gz
|
||||
sudo ./smoke-test.sh
|
||||
systemctl start athena-disaster-backup.service
|
||||
journalctl -u athena-disaster-backup.service --no-pager
|
||||
restic snapshots --tag athena-disaster
|
||||
```
|
||||
|
||||
`--check` liest das komplette gzip-Archiv und prüft dessen sichere
|
||||
`/backup`-Struktur sowie die benötigten Konfigurations- und Volume-Bäume, ohne
|
||||
Container oder Dateien zu verändern. Der reguläre Restore extrahiert und
|
||||
verwendet anschließend ausschließlich diesen einen geprüften Baum.
|
||||
Die externe Recovery-Konfiguration und die Passphrase bilden den kleinen
|
||||
Recovery-Schlüssel. Eine Kopie davon muss außerhalb beider Athena-Platten
|
||||
liegen. Ohne extern erreichbares Repository und dessen Schlüssel ist ein
|
||||
Totalausfall mathematisch nicht wiederherstellbar.
|
||||
|
||||
Das Restore verändert weder SSH noch LAN, WireGuard, Kernel, Partitionen oder
|
||||
Mounts.
|
||||
## Gemeinsame Voraussetzung aller drei Fälle
|
||||
|
||||
Debian 13 ist frisch beziehungsweise weiterhin vorhanden. Die korrekte
|
||||
Datenpartition ist formatiert und als **eigener Mountpoint** `/data`
|
||||
eingehängt. `disaster-recovery.sh` partitioniert und formatiert absichtlich
|
||||
nichts und bricht ab, wenn `/data` nur ein Verzeichnis auf der Systemplatte
|
||||
ist. Dadurch kann es nicht versehentlich die falsche Platte überschreiben.
|
||||
|
||||
Der Installer darf einen kontrollierten Neustart für NVIDIA-Treiber oder die
|
||||
stabile Netzwerkschnittstelle verlangen. Das Recovery-Skript startet Athena
|
||||
niemals selbst neu. Nach dem manuellen Neustart wird derselbe Befehl erneut
|
||||
ausgeführt; alle Schritte sind idempotent.
|
||||
|
||||
## Fall 1: Systemplatte defekt, Datenplatte erhalten
|
||||
|
||||
Nach Debian-Installation und Einhängen der alten `/data`-Platte:
|
||||
|
||||
```bash
|
||||
sudo ./disaster-recovery.sh --scenario system \
|
||||
--archive /data/docker-backups/athena-latest.tar.gz
|
||||
```
|
||||
|
||||
Das Skript birgt Konfiguration und sämtliche `/opt/mike-ai`-Projekte aus dem
|
||||
lokalen Archiv, installiert Docker/NVIDIA, verwendet die vorhandenen Modelle,
|
||||
stellt die Docker-Volumes wieder her, baut Spezialcontainer und führt den
|
||||
Smoke-Test aus.
|
||||
|
||||
Ältere Archive vor Einführung von `/etc/mike-ai/install.env` bleiben lesbar.
|
||||
Bei einem solchen Archiv muss die Installationsdatei einmal separat angegeben
|
||||
werden:
|
||||
|
||||
```bash
|
||||
sudo ./disaster-recovery.sh --scenario system \
|
||||
--archive /data/docker-backups/athena-latest.tar.gz \
|
||||
--install-config /root/mike-ai-install.env
|
||||
```
|
||||
|
||||
## Fall 2: Datenplatte defekt, Systemplatte erhalten
|
||||
|
||||
Neue Datenpartition unter `/data` einhängen und den extern aufbewahrten
|
||||
Recovery-Schlüssel bereitstellen:
|
||||
|
||||
```bash
|
||||
sudo ./disaster-recovery.sh --scenario data \
|
||||
--config /root/athena-recovery.env
|
||||
```
|
||||
|
||||
Eigene Daten und der letzte Docker-Zustand kommen aus Restic. Modellgewichte
|
||||
werden anschließend automatisch neu geladen. Je nach Internetverbindung ist
|
||||
dies der längste Teil der Wiederherstellung.
|
||||
|
||||
## Fall 3: Beide Platten defekt
|
||||
|
||||
Debian auf der neuen Systemplatte installieren, neue Datenpartition als
|
||||
`/data` einhängen, dieses Git-Repository klonen und den externen
|
||||
Recovery-Schlüssel bereitstellen:
|
||||
|
||||
```bash
|
||||
sudo ./disaster-recovery.sh --scenario all \
|
||||
--config /root/athena-recovery.env
|
||||
```
|
||||
|
||||
Der externe Snapshot liefert Installationskonfiguration, Schlüssel,
|
||||
Anwendungsquellen, Spezial-UIs, eigene Daten und Docker-Zustand. Danach werden
|
||||
Pakete, Images und Modellgewichte reproduzierbar neu aufgebaut.
|
||||
|
||||
Alternativ kann ein zuvor aus dem Dashboard heruntergeladenes Notfallpaket
|
||||
direkt verwendet werden:
|
||||
|
||||
```bash
|
||||
sudo ./disaster-recovery.sh --scenario all \
|
||||
--portable /mnt/usb/athena-portable-2026-09-10T15-00-00Z.tar.zst.age \
|
||||
--identity /mnt/usb/athena-recovery-key.txt
|
||||
```
|
||||
|
||||
## Ergebnis und Sicherheitsverhalten
|
||||
|
||||
Nach erfolgreichem Lauf gilt:
|
||||
|
||||
- Kernstack und Dashboard laufen,
|
||||
- Medium ist das aktive LLM-Standardprofil,
|
||||
- Spezialcontainer und ihre Oberflächen sind gebaut beziehungsweise erstellt,
|
||||
- GPU-intensive Spezialworker bleiben gestoppt,
|
||||
- keine automatische Umschaltung in Musik-, Bild-, Voice- oder Applio-Modus,
|
||||
- `smoke-test.sh` hat den Kern geprüft.
|
||||
|
||||
Erst danach wird der gewünschte Spezialmodus über das Dashboard aktiviert.
|
||||
|
||||
## Regelmäßige Prüfung
|
||||
|
||||
Mindestens vierteljährlich einen Restore in eine leere Test-VM beziehungsweise
|
||||
auf Testdatenträger durchführen. Ein grünes Backup-Log beweist nur, dass Daten
|
||||
geschrieben wurden; erst ein Restore-Test beweist Wiederherstellbarkeit.
|
||||
|
||||
```bash
|
||||
systemctl status athena-disaster-backup.timer
|
||||
journalctl -u athena-disaster-backup.service --since '2 days ago'
|
||||
restic snapshots --tag athena-disaster
|
||||
sudo ./restore.sh --check /data/docker-backups/athena-latest.tar.gz
|
||||
```
|
||||
|
||||
## Unraid
|
||||
|
||||
Hermes und die Fach-MCPs sind kein Bestandteil des Athena-Backups. Sie werden
|
||||
durch das vorhandene Unraid-Appdata-Backup gesichert:
|
||||
|
||||
- `/mnt/nvme-storage/appdata/Hermes-Agent`
|
||||
- die jeweiligen Appdata-Verzeichnisse der MCP-Container
|
||||
- DockerMan-Templates unter
|
||||
`/boot/config/plugins/dockerMan/templates-user/`
|
||||
|
||||
Container-Images stammen aus den dokumentierten Registries beziehungsweise den
|
||||
eigenen Gitea-Repositories. Damit besteht die Wiederherstellung aus
|
||||
Appdata-Restore plus Neuerstellung über die jeweilige Template-XML.
|
||||
|
||||
### Hermes Cron/Bot-Chat auf Unraid
|
||||
|
||||
Der offizielle Hermes-Build `0.21.0` mit Upstream-Stand `4b30b917` entfernt im
|
||||
Cron-Zustellprozess fälschlich `HERMES_HOME`. Bei einem Docker-Datenverzeichnis
|
||||
unter `/opt/data` findet `deliver=bot-chat:<profil>` dadurch vorhandene Profile
|
||||
nicht. Bis zur Übernahme des Upstream-Fixes bindet die Unraid-Vorlage dieses
|
||||
idempotente Startskript ein:
|
||||
|
||||
- Host: `/mnt/nvme-storage/appdata/Hermes-Agent/patches/025-cron-profile-root-fix`
|
||||
- Container: `/etc/cont-init.d/025-cron-profile-root-fix` (read-only)
|
||||
- Quelle: `platform/hermes/025-cron-profile-root-fix`
|
||||
|
||||
Das Skript entfernt nur die bekannte fehlerhafte Zeile. Ist sie in einem neuen
|
||||
Image nicht mehr vorhanden, bleibt der Workaround automatisch wirkungslos. Es
|
||||
stellt außerdem `/usr/local/bin/hermes` wieder her, weil der offizielle
|
||||
Container den vom eigenen Doctor erwarteten CLI-Link derzeit nicht anlegt.
|
||||
|
||||
Nach einem Restore die Datei mit Modus `0755` ins Appdata kopieren, den Mount in
|
||||
der DockerMan-Vorlage kontrollieren und den Container neu erstellen. Prüfung:
|
||||
|
||||
```bash
|
||||
docker logs Hermes-Agent 2>&1 | grep cron-profile-root-fix
|
||||
docker exec Hermes-Agent hermes cron doctor
|
||||
```
|
||||
|
||||
## Kontrolle
|
||||
|
||||
```bash
|
||||
docker compose --env-file /etc/mike-ai/stack.env ps
|
||||
sudo ./restore.sh --check /data/docker-backups/athena-latest.tar.gz
|
||||
curl -fsS http://192.168.1.212:8099/health
|
||||
sudo ./smoke-test.sh
|
||||
```
|
||||
|
||||
Anschließend einen Hermes-Chat, einen Router-Aufruf und je eine kleine
|
||||
read-only-Abfrage der benötigten MCPs testen.
|
||||
Hermes und die Fach-MCPs laufen auf Unraid und sind kein Bestandteil des
|
||||
Athena-Restores. Sie werden weiterhin über das Unraid-Appdata-Backup gesichert.
|
||||
Das Athena-Disaster-Repository muss auf einem anderen Datenträger beziehungsweise
|
||||
Storage-Pool als das zu schützende Athena-System liegen.
|
||||
Reference in new issue
Block a user