Files
hx-ki.com2/COM2_DOCTOR_ONE_SHOT.sh
2026-03-06 15:22:40 +00:00

138 lines
4.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
set -euo pipefail
DIR="/opt/hx-ki/com2-stack"
F="$DIR/docker-compose.yml"
NET="hxki-internal"
TS="$(date +%Y%m%d-%H%M%S)"
BK="$DIR/backup-$TS"
echo "=== COM2 DOCTOR (one-shot, deterministisch) ==="
echo "Autorität: $F"
echo "Backup: $BK"
mkdir -p "$BK"
# 0) Preconditions
[ -f "$F" ] || { echo "FEHLT: $F"; exit 1; }
cp -a "$F" "$BK/docker-compose.yml.orig"
# 1) Host-Caddy darf NICHT Port 80/443 blocken, wenn Docker-Caddy laufen soll
if systemctl is-active --quiet caddy 2>/dev/null; then
echo "[1] Stoppe host-caddy (systemd), damit Docker-Caddy 80/443 bekommt"
systemctl stop caddy
else
echo "[1] OK: host-caddy ist nicht aktiv"
fi
# 2) Docker Netzwerk sicherstellen (external)
docker network inspect "$NET" >/dev/null 2>&1 || { echo "[2] Erzeuge Docker-Netzwerk: $NET"; docker network create "$NET" >/dev/null; }
echo "[2] OK: Netzwerk existiert: $NET"
# 3) Compose YAML MUSS valide sein sonst: Restore und STOP mit Zeilenanzeige
echo "[3] Validate Compose YAML"
if ! docker compose -f "$F" config >/dev/null 2>&1; then
echo "FAIL: Compose ist NICHT valide."
echo "---- Parser-Fehler ----"
docker compose -f "$F" config 2>&1 | tail -n 30 || true
echo "---- Zeilen um die vermutete Fehlerstelle (45-80) ----"
nl -ba "$F" | sed -n '45,80p' || true
echo
echo "Auto-Restore auf Backup und STOP."
cp -a "$BK/docker-compose.yml.orig" "$F"
exit 1
fi
echo "[3] OK: Compose ist valide"
# 4) Pflicht-Services auf COM2 (laut deiner Vorgabe: autark)
echo "[4] Prüfe Pflicht-Services im Compose (ohne Umbau)"
python3 - <<'PY'
import re, pathlib, sys
p = pathlib.Path("/opt/hx-ki/com2-stack/docker-compose.yml")
s = p.read_text()
m = re.search(r'(?ms)^services:\s*\n(.*?)(?=^\S|\Z)', s)
if not m:
print("FAIL: Kein Top-Level 'services:' Block.")
sys.exit(1)
block = m.group(1)
names = re.findall(r'(?m)^\s{2}([A-Za-z0-9_.-]+):\s*$', block)
need = ["hx-caddy","hxki-n8n","hxki-postgres","hxki-mariadb","hxki-mautic"]
missing = [x for x in need if x not in names]
print("Services gefunden:", ", ".join(names))
if missing:
print("FAIL: Pflicht-Services fehlen:", ", ".join(missing))
sys.exit(2)
print("OK: Pflicht-Services vorhanden.")
PY
# 5) hxki-internal als external:true MUSS im Compose vorhanden sein (sonst knallt network-ref)
echo "[5] Prüfe: networks/hxki-internal external:true"
python3 - <<'PY'
from pathlib import Path
import re, sys
p = Path("/opt/hx-ki/com2-stack/docker-compose.yml")
s = p.read_text()
# sehr konservativ: nur prüfen, nicht "raten"
if not re.search(r'(?ms)^networks:\s*\n(?:.*\n)*?\s{2}hxki-internal:\s*\n(?:.*\n)*?\s{4}external:\s*true\s*$', s):
print("FAIL: networks: hxki-internal: external:true fehlt oder ist anders.")
print("Zeilen-Hinweis:")
import subprocess, shlex
subprocess.run(["bash","-lc",f"nl -ba {p} | grep -nE '^(\\s*networks:|\\s{{2}}hxki-internal:|\\s{{4}}external:)' -n || true"])
sys.exit(3)
print("OK: networks/hxki-internal external:true gefunden.")
PY
# 6) n8n config MUSS gültiges JSON sein (dein log beweist, dass es kaputt war)
# Wir reparieren NUR das deterministisch: config als JSON resetten, ohne Workflows/DB anzufassen.
echo "[6] Fix: n8n config JSON (nur wenn kaputt)"
MOUNT_SRC="/data/HXKI_WORKSPACE/router"
CFG="$MOUNT_SRC/config"
if [ -d "$MOUNT_SRC" ]; then
docker stop hxki-n8n >/dev/null 2>&1 || true
if [ -f "$CFG" ]; then
if python3 - <<PY >/dev/null 2>&1
import json
json.load(open("$CFG","r"))
PY
then
echo "OK: $CFG ist gültiges JSON (nichts zu tun)"
else
echo "WARN: $CFG ist KEIN gültiges JSON -> schreibe minimal gültig + Backup"
cp -a "$CFG" "$CFG.bak.$TS"
cat > "$CFG" <<JSON
{"encryptionKey":"","instanceId":""}
JSON
chown 1000:1000 "$CFG" || true
chmod 600 "$CFG" || true
fi
else
echo "INFO: $CFG existiert nicht -> wird von n8n beim Start erzeugt"
fi
# Rechte auf Mount (konservativ)
chown -R 1000:1000 "$MOUNT_SRC" || true
chmod -R u+rwX "$MOUNT_SRC" || true
chmod -R g+rwX "$MOUNT_SRC" || true
docker start hxki-n8n >/dev/null 2>&1 || true
else
echo "WARN: $MOUNT_SRC fehlt -> n8n Mount passt nicht (keine Reparatur)"
fi
# 7) Orchester hoch (alles oder nichts)
echo "[7] Orchester UP (alles zusammen)"
cd "$DIR"
docker compose up -d --remove-orphans
echo "[8] Status (Container)"
docker ps --format 'NAME={{.Names}} STATUS={{.Status}} PORTS={{.Ports}}' | egrep 'hxki-|hx-' || true
echo "[9] Netzwerk-Mitglieder: $NET"
docker network inspect "$NET" --format '{{range $id,$c := .Containers}}{{println $c.Name}}{{end}}' | sort || true
# 10) Caddy -> n8n intern test (nur intern, ohne "lokal 127.0.0.1")
echo "[10] Caddy->n8n Service-Test (intern)"
docker exec -it hx-caddy sh -lc 'wget -qO- http://hxki-n8n:5678/ >/dev/null && echo OK_CADDY_TO_N8N || echo FAIL_CADDY_TO_N8N' || true
echo "=== ENDE ==="