diff --git a/README.md b/README.md index 098d600..fa3f57f 100644 --- a/README.md +++ b/README.md @@ -74,6 +74,20 @@ Autobackups einmalig in der Weboberfläche aktivieren: (*Einstellungen → System → Backups → Wiederherstellen*) oder bei einer Neuinstallation direkt im Einrichtungs-Assistenten. +## MongoDB auf 7.0 migrieren + +```bash +./migrate-mongo.sh +``` + +Für den Fall, dass der Stack auf neue Hardware umzieht (oder ursprünglich mit +Mongo 4.4 eingerichtet wurde, die CPU aber mehr kann): Das Skript prüft zuerst +die CPU (AVX bzw. ARMv8.2) und bricht ohne Änderungen ab, wenn MongoDB 5+ +dort nicht laufen kann. Andernfalls erstellt es ein Komplett-Backup und +migriert die Datenbank schrittweise in-place (4.4 → 5.0 → 6.0 → 7.0, inkl. +`featureCompatibilityVersion`), pinnt `MONGO_VERSION=7.0` in der `.env` und +startet den Stack wieder. + ## Verzeichnisstruktur ``` diff --git a/migrate-mongo.sh b/migrate-mongo.sh new file mode 100755 index 0000000..8572cc8 --- /dev/null +++ b/migrate-mongo.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# Migriert die MongoDB-Datenbank in-place auf Version 7.0. +# +# MongoDB erlaubt keine Sprünge über mehrere Major-Versionen, daher wird +# schrittweise migriert (4.4 -> 5.0 -> 6.0 -> 7.0) und nach jedem Schritt die +# featureCompatibilityVersion angehoben. +# +# Vorher wird geprüft, ob die CPU das überhaupt kann (MongoDB 5+ braucht auf +# x86_64 AVX, auf ARM64 ARMv8.2) — ohne das bricht das Skript ab, ohne etwas +# zu verändern. Außerdem wird ein Komplett-Backup erstellt. +set -euo pipefail +cd "$(dirname "$0")" + +TARGET="7.0" +MIGRATION_PATH=("5.0" "6.0" "7.0") +DB_DATA="$PWD/data/mongodb" +TMP_NAME="unifi-db-migrate" + +# ---------- 1. CPU-Prüfung ---------- +arch="$(uname -m)" +flags="$(grep -m1 -iE '^(flags|Features)' /proc/cpuinfo 2>/dev/null || true)" +cpu_ok=false +case "$arch" in + x86_64) grep -qw avx <<< "$flags" && cpu_ok=true ;; + aarch64|arm64) grep -qw asimddp <<< "$flags" && cpu_ok=true ;; +esac +if [[ "$cpu_ok" != true ]]; then + echo "ABBRUCH: Diese CPU ($arch) unterstützt kein AVX bzw. ARMv8.2." + echo "MongoDB 5+ würde auf diesem Rechner nicht starten — Migration nicht möglich." + echo "Es wurde nichts verändert." + exit 1 +fi +echo "==> CPU-Prüfung bestanden ($arch): Migration auf mongo:$TARGET möglich." + +# ---------- 2. Ausgangslage prüfen ---------- +[[ -f .env ]] || { echo "FEHLER: .env fehlt."; exit 1; } +CURRENT="$(grep '^MONGO_VERSION=' .env | cut -d= -f2 || true)" +CURRENT="${CURRENT:-4.4}" +if [[ "$CURRENT" == "$TARGET" ]]; then + echo "MongoDB ist bereits auf $TARGET gepinnt — nichts zu tun." + exit 0 +fi +if [[ ! -d "$DB_DATA" ]] || [[ -z "$(ls -A "$DB_DATA" 2>/dev/null)" ]]; then + echo "Keine bestehende Datenbank gefunden — einfach ./start.sh ausführen," + echo "das richtet direkt mongo:$TARGET ein." + exit 1 +fi +echo "==> Migriere von mongo:$CURRENT auf mongo:$TARGET" + +# ---------- 3. Sicherheits-Backup ---------- +echo "==> Komplett-Backup vor der Migration..." +./backup.sh --full + +# ---------- 4. Stack stoppen ---------- +echo "==> Container stoppen..." +docker-compose down +docker rm -f "$TMP_NAME" >/dev/null 2>&1 || true + +# Hilfsfunktionen: temporären mongod starten/abfragen/stoppen +mongo_eval() { + docker exec "$TMP_NAME" sh -c \ + 'if command -v mongosh >/dev/null; then mongosh --quiet --eval "$0"; else mongo --quiet --eval "$0"; fi' \ + "$1" +} +wait_for_mongo() { + local i + for i in $(seq 1 60); do + if mongo_eval 'db.adminCommand({ping:1}).ok' >/dev/null 2>&1; then return 0; fi + sleep 2 + done + echo "FEHLER: mongod wurde nicht rechtzeitig bereit."; return 1 +} +run_step() { + local version="$1" + echo "==> Schritt: mongo:$version starten..." + docker run -d --name "$TMP_NAME" -v "$DB_DATA":/data/db "mongo:$version" >/dev/null + wait_for_mongo + local fcv_cmd + if [[ "$version" == "7.0" ]]; then + fcv_cmd="db.adminCommand({setFeatureCompatibilityVersion: \"$version\", confirm: true})" + else + fcv_cmd="db.adminCommand({setFeatureCompatibilityVersion: \"$version\"})" + fi + echo " featureCompatibilityVersion -> $version" + mongo_eval "$fcv_cmd" >/dev/null + docker stop "$TMP_NAME" >/dev/null + docker rm "$TMP_NAME" >/dev/null + echo " Schritt $version abgeschlossen." +} + +# ---------- 5. Schrittweise migrieren ---------- +started=false +for step in "${MIGRATION_PATH[@]}"; do + # Schritte unterhalb der aktuellen Version überspringen (z.B. Start bei 5.0) + if [[ "$started" == false ]]; then + if [[ "$(printf '%s\n' "$CURRENT" "$step" | sort -V | head -1)" == "$CURRENT" && "$CURRENT" != "$step" ]]; then + started=true + else + continue + fi + fi + run_step "$step" +done + +# ---------- 6. Pin aktualisieren und Stack starten ---------- +sed -i "s/^MONGO_VERSION=.*/MONGO_VERSION=$TARGET/" .env +echo "==> MONGO_VERSION=$TARGET in .env gesetzt." +echo "==> Stack wieder starten..." +docker-compose pull unifi-db +docker-compose up -d + +echo "" +echo "Migration abgeschlossen. Prüfen mit:" +echo " docker exec unifi-db mongosh --quiet --eval 'db.version()'" +echo " curl -sk https://localhost:8443/status" +echo "Das Sicherheits-Backup liegt in ./backups/ und kann bei Problemen" +echo "mit ./restore.sh wiederhergestellt werden."