101 lines
3.6 KiB
Bash
Executable File
101 lines
3.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Self-contained Athena reinstall entry point. This file is copied into a
|
|
# root-only recovery kit on /data; it is not run during normal installation.
|
|
set -Eeuo pipefail
|
|
umask 077
|
|
|
|
KIT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
|
CONFIG="$KIT_DIR/kit.env"
|
|
WORK_DIR=/var/lib/mike-ai-data-reinstall
|
|
SERVICE=/etc/systemd/system/mike-ai-data-reinstall.service
|
|
|
|
die() { printf 'FEHLER: %s\n' "$*" >&2; exit 1; }
|
|
log() { printf '\n==> %s\n' "$*"; }
|
|
[[ $EUID -eq 0 ]] || die "Bitte als root ausführen."
|
|
[[ -s $CONFIG ]] || die "kit.env fehlt im Recovery-Kit."
|
|
# shellcheck disable=SC1090
|
|
source "$CONFIG"
|
|
|
|
required=(RECOVERY_COMMIT RECOVERY_BUNDLE SOURCE_BUNDLE AGE_IDENTITY)
|
|
for name in "${required[@]}"; do
|
|
[[ -n ${!name:-} ]] || die "Pflichtwert $name fehlt."
|
|
done
|
|
for file in "$RECOVERY_BUNDLE" "$SOURCE_BUNDLE" "$AGE_IDENTITY"; do
|
|
[[ -s $KIT_DIR/$file ]] || die "Recovery-Datei fehlt: $file"
|
|
done
|
|
|
|
log "Recovery-Kit kryptografisch prüfen"
|
|
(cd "$KIT_DIR" && sha256sum -c SHA256SUMS)
|
|
|
|
log "Persistenten Mount für die Data-SSD sicherstellen"
|
|
[[ $(findmnt -n -o TARGET --target "$KIT_DIR") == /data ]] || \
|
|
die "Recovery-Kit liegt nicht auf dem eingehängten /data-Dateisystem."
|
|
if ! findmnt -s -n -o TARGET | grep -qx /data; then
|
|
source_device=$(findmnt -n -o SOURCE --target "$KIT_DIR")
|
|
source_uuid=$(blkid -s UUID -o value "$source_device")
|
|
source_type=$(findmnt -n -o FSTYPE --target "$KIT_DIR")
|
|
[[ -n $source_uuid && -n $source_type ]] || \
|
|
die "UUID oder Dateisystemtyp der Data-SSD konnte nicht bestimmt werden."
|
|
printf 'UUID=%s /data %s defaults,nofail,x-systemd.device-timeout=30 0 2\n' \
|
|
"$source_uuid" "$source_type" >>/etc/fstab
|
|
systemctl daemon-reload
|
|
fi
|
|
|
|
log "Minimale Wiederherstellungswerkzeuge installieren"
|
|
apt-get update
|
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
|
|
age ca-certificates git rsync
|
|
|
|
install -d -m 0700 "$WORK_DIR"
|
|
if [[ ! -d $WORK_DIR/repository/.git ]]; then
|
|
git clone "$KIT_DIR/$SOURCE_BUNDLE" "$WORK_DIR/repository"
|
|
fi
|
|
git -C "$WORK_DIR/repository" checkout --detach "$RECOVERY_COMMIT"
|
|
[[ $(git -C "$WORK_DIR/repository" rev-parse HEAD) == "$RECOVERY_COMMIT" ]] || \
|
|
die "Der geforderte Recovery-Commit ist nicht ausgecheckt."
|
|
|
|
attempt=0
|
|
[[ ! -s $WORK_DIR/attempt ]] || attempt=$(<"$WORK_DIR/attempt")
|
|
(( attempt += 1 ))
|
|
printf '%s\n' "$attempt" >"$WORK_DIR/attempt"
|
|
(( attempt <= 3 )) || die "Mehr als drei automatische Recovery-Versuche; Abbruch gegen Bootschleife."
|
|
|
|
log "Bare-Metal-Wiederherstellung ausführen (Versuch $attempt/3)"
|
|
set +e
|
|
"$WORK_DIR/repository/platform/recovery/restore-recovery-bundle.sh" \
|
|
"$KIT_DIR/$RECOVERY_BUNDLE" "$KIT_DIR/$AGE_IDENTITY"
|
|
status=$?
|
|
set -e
|
|
|
|
if [[ $status == 20 || $status == 21 ]]; then
|
|
log "Ein kontrollierter Treiber-/Netzwerk-Neustart ist erforderlich"
|
|
cat >"$SERVICE" <<EOF
|
|
[Unit]
|
|
Description=Resume MikeAI data-disk disaster recovery
|
|
After=network-online.target local-fs.target
|
|
Wants=network-online.target
|
|
RequiresMountsFor=/data
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
ExecStart=$KIT_DIR/reinstall-athena.sh --resume
|
|
StandardOutput=append:/var/log/mike-ai-data-reinstall.log
|
|
StandardError=append:/var/log/mike-ai-data-reinstall.log
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
systemctl daemon-reload
|
|
systemctl enable mike-ai-data-reinstall.service
|
|
sync
|
|
systemctl reboot
|
|
exit 0
|
|
fi
|
|
[[ $status == 0 ]] || die "Wiederherstellung ist mit Status $status fehlgeschlagen."
|
|
|
|
systemctl disable mike-ai-data-reinstall.service >/dev/null 2>&1 || true
|
|
rm -f "$SERVICE" "$WORK_DIR/attempt"
|
|
systemctl daemon-reload
|
|
printf '\nDATA_DISK_REINSTALL_OK\n'
|
|
printf 'OpenWebUI, Router, Modelle und MCPs wurden wiederhergestellt.\n'
|