Automate reference host data restore
This commit is contained in:
@@ -37,5 +37,27 @@
|
|||||||
12. Standardbenchmark und Sicherheitsprüfung ausführen.
|
12. Standardbenchmark und Sicherheitsprüfung ausführen.
|
||||||
13. Erst danach Clients umstellen.
|
13. Erst danach Clients umstellen.
|
||||||
|
|
||||||
|
## Referenz-Backup automatisiert einspielen
|
||||||
|
|
||||||
|
Nach einem erfolgreichen Lauf von `install.sh` kann eine Sicherung des alten
|
||||||
|
Referenzhosts gezielt importiert werden:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo ./platform/migration/restore-reference-backup.sh \
|
||||||
|
/data/ki-migration-backup-YYYYMMDD
|
||||||
|
```
|
||||||
|
|
||||||
|
Das Skript prüft zuerst die Archiv-Hashes und übernimmt ausschließlich:
|
||||||
|
|
||||||
|
- die persistente OpenWebUI-Datenbank samt Einstellungen und Uploads,
|
||||||
|
- den dazugehörigen WebUI- und Router-Schlüssel,
|
||||||
|
- die freigegebenen HA-, ARR- und Unraid-Secrets,
|
||||||
|
- `runraid`, dessen privaten Schlüssel, Zertifikat und Known-Hosts-Datei.
|
||||||
|
|
||||||
|
Es übernimmt bewusst **keine** alten Compose-Dateien, Routerprofile,
|
||||||
|
Experimentdienste oder `.before-*`-Altstände. Vor dem Ersetzen des frischen
|
||||||
|
OpenWebUI-Volumes wird unter `/data/open-webui-before-restore-*.tar.gz` eine
|
||||||
|
Rückfallsicherung erstellt. Secret-Werte werden nicht ausgegeben.
|
||||||
|
|
||||||
Der alte Host bleibt bis zum bestandenen Abnahmetest unverändert und dient nur
|
Der alte Host bleibt bis zum bestandenen Abnahmetest unverändert und dient nur
|
||||||
als Referenz. Es werden keine Caches oder unbekannten Altverzeichnisse kopiert.
|
als Referenz. Es werden keine Caches oder unbekannten Altverzeichnisse kopiert.
|
||||||
|
|||||||
@@ -178,9 +178,12 @@ run-acceptance-tests
|
|||||||
```
|
```
|
||||||
|
|
||||||
`platform/mcp/install-tools.sh` installiert den Webbereich automatisch und
|
`platform/mcp/install-tools.sh` installiert den Webbereich automatisch und
|
||||||
aktiviert HA, ARR und Unraid nur bei vorhandenen Secret-/Programmdateien. Offen
|
aktiviert HA, ARR und Unraid nur bei vorhandenen Secret-/Programmdateien.
|
||||||
bleiben ein kompletter Leerhost-Probelauf und der automatisierte Import einer
|
`platform/migration/restore-reference-backup.sh` importiert eine bestehende
|
||||||
bereits bestehenden Open-WebUI-Datenbank.
|
OpenWebUI-Datenbank und ausschließlich die freigegebenen Tool-Secrets, ohne
|
||||||
|
experimentelle Altcontainer zurückzubringen. Der Leerhost-Probelauf wird auf
|
||||||
|
Athena praktisch protokolliert und seine Korrekturen fließen direkt in den
|
||||||
|
Installer zurück.
|
||||||
|
|
||||||
Jeder Schritt muss wiederholbar, einzeln prüfbar und bei Fehlern abbrechbar
|
Jeder Schritt muss wiederholbar, einzeln prüfbar und bei Fehlern abbrechbar
|
||||||
sein. Ein fehlgeschlagener Schritt darf keinen halb aktivierten Dienst
|
sein. Ein fehlgeschlagener Schritt darf keinen halb aktivierten Dienst
|
||||||
|
|||||||
+119
@@ -0,0 +1,119 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Restore persistent UI data and the approved secret subset from a reference
|
||||||
|
# host backup without reviving its obsolete containers or configuration files.
|
||||||
|
set -Eeuo pipefail
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
BACKUP=${1:-}
|
||||||
|
STACK_DIR=${STACK_DIR:-/opt/mike-ai/stack}
|
||||||
|
SECRETS_DIR=${SECRETS_DIR:-/etc/mike-ai}
|
||||||
|
OPENWEBUI_VOLUME=${OPENWEBUI_VOLUME:-mike-ai_open-webui-data}
|
||||||
|
|
||||||
|
die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
|
||||||
|
log() { printf '\n==> %s\n' "$*"; }
|
||||||
|
|
||||||
|
[[ $EUID -eq 0 ]] || die "Bitte als root ausführen."
|
||||||
|
[[ -n $BACKUP && -d $BACKUP ]] || \
|
||||||
|
die "Aufruf: $0 /pfad/zum/ki-migration-backup"
|
||||||
|
[[ -f $BACKUP/SHA256SUMS ]] || die "SHA256SUMS fehlt."
|
||||||
|
[[ -f $SECRETS_DIR/stack.env ]] || die "$SECRETS_DIR/stack.env fehlt."
|
||||||
|
|
||||||
|
ui_archive=$BACKUP/archives/open-webui-migrated.tar.gz
|
||||||
|
mcp_archive=$BACKUP/archives/mcp-and-search-config.tar.gz
|
||||||
|
for archive in "$ui_archive" "$mcp_archive"; do
|
||||||
|
[[ -f $archive ]] || die "Archiv fehlt: $archive"
|
||||||
|
expected=$(awk -v suffix="/${archive#"$BACKUP"/}" \
|
||||||
|
'$2 ~ suffix "$" {print $1; exit}' "$BACKUP/SHA256SUMS")
|
||||||
|
[[ -n $expected ]] || die "Keine Prüfsumme für $archive gefunden."
|
||||||
|
actual=$(sha256sum "$archive" | awk '{print $1}')
|
||||||
|
[[ $actual == "$expected" ]] || die "Prüfsumme falsch: $archive"
|
||||||
|
done
|
||||||
|
|
||||||
|
stage=$(mktemp -d /data/mike-ai-restore.XXXXXX)
|
||||||
|
trap 'rm -rf "$stage"' EXIT
|
||||||
|
|
||||||
|
log "OpenWebUI-Sicherung entpacken und prüfen"
|
||||||
|
tar -xzf "$ui_archive" -C "$stage"
|
||||||
|
ui_source=$stage/open-webui-migrated
|
||||||
|
[[ -s $ui_source/data/webui.db ]] || die "OpenWebUI-Datenbank fehlt oder ist leer."
|
||||||
|
[[ -f $ui_source/openwebui.env ]] || die "OpenWebUI-Umgebung fehlt."
|
||||||
|
|
||||||
|
old_webui_key=$(sed -n 's/^WEBUI_SECRET_KEY=//p' \
|
||||||
|
"$ui_source/openwebui.env" | head -n 1)
|
||||||
|
[[ -n $old_webui_key ]] || die "WEBUI_SECRET_KEY fehlt in der Sicherung."
|
||||||
|
|
||||||
|
log "Freigegebene MCP-Secrets isoliert entpacken"
|
||||||
|
mkdir -p "$stage/approved"
|
||||||
|
tar -xzf "$mcp_archive" -C "$stage/approved" \
|
||||||
|
etc/mike-ai/router-api-key \
|
||||||
|
etc/mike-ai/homeassistant-admin-mcp.env \
|
||||||
|
etc/mike-ai/arr-mcp.env \
|
||||||
|
etc/mike-ai/runraid/.env \
|
||||||
|
etc/mike-ai/runraid/homeserver-cert.pem \
|
||||||
|
etc/mike-ai/keys/unraid_root \
|
||||||
|
etc/mike-ai/ssh/known_hosts_unraid_ai \
|
||||||
|
usr/local/bin/runraid
|
||||||
|
|
||||||
|
old_router_key=$(<"$stage/approved/etc/mike-ai/router-api-key")
|
||||||
|
[[ -n $old_router_key ]] || die "Router-Key in der Sicherung ist leer."
|
||||||
|
|
||||||
|
set_env_value() {
|
||||||
|
local file=$1 key=$2 value=$3 tmp
|
||||||
|
tmp=$(mktemp "${file}.XXXXXX")
|
||||||
|
awk -v key="$key" -v value="$value" '
|
||||||
|
BEGIN { done=0 }
|
||||||
|
$0 ~ "^" key "=" { print key "=" value; done=1; next }
|
||||||
|
{ print }
|
||||||
|
END { if (!done) print key "=" value }
|
||||||
|
' "$file" >"$tmp"
|
||||||
|
install -m 0600 "$tmp" "$file"
|
||||||
|
rm -f "$tmp"
|
||||||
|
}
|
||||||
|
|
||||||
|
log "Aktuellen leeren UI-Stand als Rückfall sichern"
|
||||||
|
volume_path=$(docker volume inspect -f '{{.Mountpoint}}' "$OPENWEBUI_VOLUME")
|
||||||
|
fallback=/data/open-webui-before-restore-$(date +%Y%m%d-%H%M%S).tar.gz
|
||||||
|
tar -czf "$fallback" -C "$volume_path" .
|
||||||
|
|
||||||
|
log "OpenWebUI-Daten atomar ersetzen"
|
||||||
|
docker stop mike-ai-open-webui >/dev/null 2>&1 || true
|
||||||
|
rsync -a --delete "$ui_source/data/" "$volume_path/"
|
||||||
|
|
||||||
|
log "Schlüssel und aktuelle Tool-Secrets wiederherstellen"
|
||||||
|
set_env_value "$SECRETS_DIR/stack.env" WEBUI_SECRET_KEY "$old_webui_key"
|
||||||
|
set_env_value "$SECRETS_DIR/stack.env" ROUTER_API_KEY "$old_router_key"
|
||||||
|
|
||||||
|
install -d -m 0700 "$SECRETS_DIR/runraid" "$SECRETS_DIR/keys" "$SECRETS_DIR/ssh"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/homeassistant-admin-mcp.env" \
|
||||||
|
"$SECRETS_DIR/homeassistant-admin-mcp.env"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/arr-mcp.env" \
|
||||||
|
"$SECRETS_DIR/arr-mcp.env"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/runraid/.env" \
|
||||||
|
"$SECRETS_DIR/runraid/.env"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/runraid/homeserver-cert.pem" \
|
||||||
|
"$SECRETS_DIR/runraid/homeserver-cert.pem"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/keys/unraid_root" \
|
||||||
|
"$SECRETS_DIR/keys/unraid_root"
|
||||||
|
install -m 0600 "$stage/approved/etc/mike-ai/ssh/known_hosts_unraid_ai" \
|
||||||
|
"$SECRETS_DIR/ssh/known_hosts_unraid_ai"
|
||||||
|
install -m 0755 "$stage/approved/usr/local/bin/runraid" /usr/local/bin/runraid
|
||||||
|
|
||||||
|
log "Tool-Container mit der neuen Stackdefinition aktivieren"
|
||||||
|
"$STACK_DIR/platform/mcp/install-tools.sh"
|
||||||
|
|
||||||
|
log "Router und OpenWebUI mit den wiederhergestellten Schlüsseln neu erstellen"
|
||||||
|
cd "$STACK_DIR"
|
||||||
|
docker compose --env-file "$SECRETS_DIR/stack.env" up -d --force-recreate \
|
||||||
|
router open-webui
|
||||||
|
|
||||||
|
deadline=$((SECONDS + 180))
|
||||||
|
for container in mike-ai-router mike-ai-open-webui; do
|
||||||
|
until [[ $(docker inspect -f '{{if .State.Health}}{{.State.Health.Status}}{{else}}{{.State.Status}}{{end}}' \
|
||||||
|
"$container" 2>/dev/null || true) == healthy ]]; do
|
||||||
|
(( SECONDS < deadline )) || die "$container wurde nicht rechtzeitig gesund."
|
||||||
|
sleep 2
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
log "Wiederherstellung abgeschlossen"
|
||||||
|
printf 'Rückfallsicherung des vorherigen UI-Stands: %s\n' "$fallback"
|
||||||
Reference in New Issue
Block a user