200 lines
7.4 KiB
Bash
Executable File
200 lines
7.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
DIR="/opt/hx-ki/com2-stack"
|
|
F="$DIR/docker-compose.yml"
|
|
ENVF="$DIR/.env"
|
|
NET="hxki-internal"
|
|
TS="$(date +%Y%m%d-%H%M%S)"
|
|
BK="$DIR/backup-fix-$TS"
|
|
mkdir -p "$BK"
|
|
|
|
echo "=== COM2 FIX ONE-SHOT ==="
|
|
echo "Autorität: $F"
|
|
[ -f "$F" ] || { echo "FEHLT: $F"; exit 1; }
|
|
|
|
cp -a "$F" "$BK/docker-compose.yml.pre"
|
|
|
|
# Netzwerk muss als external existieren (Host)
|
|
docker network inspect "$NET" >/dev/null 2>&1 || docker network create "$NET" >/dev/null
|
|
|
|
# .env laden (falls vorhanden)
|
|
if [ -f "$ENVF" ]; then
|
|
set -a
|
|
# shellcheck disable=SC1090
|
|
. "$ENVF"
|
|
set +a
|
|
fi
|
|
|
|
# Helper: ENV aus Container ziehen
|
|
get_env_from_container() {
|
|
local c="$1" key="$2"
|
|
docker inspect "$c" --format '{{range .Config.Env}}{{println .}}{{end}}' \
|
|
| awk -F= -v k="$key" '$1==k{print substr($0, index($0,"=")+1)}' \
|
|
| head -n1
|
|
}
|
|
|
|
echo
|
|
echo "[1] Container vorhanden?"
|
|
for c in hxki-postgres hxki-mariadb hxki-n8n hxki-mautic; do
|
|
docker inspect "$c" >/dev/null 2>&1 || { echo "FEHLT Container: $c"; exit 1; }
|
|
done
|
|
|
|
echo
|
|
echo "[2] Postgres: setze/angleiche User/DB/PW (damit n8n startet)"
|
|
|
|
# Werte entweder aus .env oder aus n8n-Container ENV
|
|
PG_USER="${PG_USER:-$(get_env_from_container hxki-n8n DB_POSTGRESDB_USER)}"
|
|
PG_PASSWORD="${PG_PASSWORD:-$(get_env_from_container hxki-n8n DB_POSTGRESDB_PASSWORD)}"
|
|
PG_DB="${PG_DB:-$(get_env_from_container hxki-n8n DB_POSTGRESDB_DATABASE)}"
|
|
|
|
[ -n "${PG_USER:-}" ] || { echo "FEHLT: PG_USER (in $ENVF oder n8n ENV)"; exit 1; }
|
|
[ -n "${PG_PASSWORD:-}" ] || { echo "FEHLT: PG_PASSWORD (in $ENVF oder n8n ENV)"; exit 1; }
|
|
[ -n "${PG_DB:-}" ] || { echo "FEHLT: PG_DB (in $ENVF oder n8n ENV)"; exit 1; }
|
|
|
|
docker exec -u postgres -i hxki-postgres psql -v ON_ERROR_STOP=1 -d postgres <<SQL
|
|
DO \$\$
|
|
BEGIN
|
|
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname='${PG_USER}') THEN
|
|
CREATE ROLE ${PG_USER} LOGIN PASSWORD '${PG_PASSWORD}';
|
|
ELSE
|
|
ALTER ROLE ${PG_USER} WITH LOGIN PASSWORD '${PG_PASSWORD}';
|
|
END IF;
|
|
|
|
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname='${PG_DB}') THEN
|
|
CREATE DATABASE ${PG_DB} OWNER ${PG_USER};
|
|
END IF;
|
|
END
|
|
\$\$;
|
|
GRANT ALL PRIVILEGES ON DATABASE ${PG_DB} TO ${PG_USER};
|
|
SQL
|
|
|
|
echo "OK: Postgres User/DB/PW angeglichen."
|
|
|
|
echo
|
|
echo "[3] MariaDB: setze/angleiche Mautic DB/User/PW (damit mautic startet)"
|
|
|
|
# Root-PW aus MariaDB Container ENV
|
|
MDB_ROOT_PW="$(get_env_from_container hxki-mariadb MYSQL_ROOT_PASSWORD || true)"
|
|
[ -n "${MDB_ROOT_PW:-}" ] || MDB_ROOT_PW="$(get_env_from_container hxki-mariadb MARIADB_ROOT_PASSWORD || true)"
|
|
[ -n "${MDB_ROOT_PW:-}" ] || { echo "FEHLT: MariaDB Root-Passwort (MYSQL_ROOT_PASSWORD/MARIADB_ROOT_PASSWORD im Container)"; exit 1; }
|
|
|
|
# Mautic Zielwerte: aus Mautic Container ENV (Quelle der Wahrheit)
|
|
MAUTIC_DB_HOST="$(get_env_from_container hxki-mautic MAUTIC_DB_HOST || true)"
|
|
MAUTIC_DB_USER="$(get_env_from_container hxki-mautic MAUTIC_DB_USER || true)"
|
|
MAUTIC_DB_PASSWORD="$(get_env_from_container hxki-mautic MAUTIC_DB_PASSWORD || true)"
|
|
MAUTIC_DB_NAME="$(get_env_from_container hxki-mautic MAUTIC_DB_NAME || true)"
|
|
|
|
# Fallbacks (falls Image andere Keys nutzt)
|
|
[ -n "${MAUTIC_DB_USER:-}" ] || MAUTIC_DB_USER="$(get_env_from_container hxki-mautic MYSQL_USER || true)"
|
|
[ -n "${MAUTIC_DB_PASSWORD:-}" ] || MAUTIC_DB_PASSWORD="$(get_env_from_container hxki-mautic MYSQL_PASSWORD || true)"
|
|
[ -n "${MAUTIC_DB_NAME:-}" ] || MAUTIC_DB_NAME="$(get_env_from_container hxki-mautic MYSQL_DATABASE || true)"
|
|
|
|
[ -n "${MAUTIC_DB_USER:-}" ] || { echo "FEHLT: MAUTIC_DB_USER (im hxki-mautic ENV)"; exit 1; }
|
|
[ -n "${MAUTIC_DB_PASSWORD:-}" ] || { echo "FEHLT: MAUTIC_DB_PASSWORD (im hxki-mautic ENV)"; exit 1; }
|
|
[ -n "${MAUTIC_DB_NAME:-}" ] || { echo "FEHLT: MAUTIC_DB_NAME (im hxki-mautic ENV)"; exit 1; }
|
|
|
|
docker exec -i hxki-mariadb mysql -uroot -p"${MDB_ROOT_PW}" <<SQL
|
|
CREATE DATABASE IF NOT EXISTS \`${MAUTIC_DB_NAME}\` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
|
|
CREATE USER IF NOT EXISTS '${MAUTIC_DB_USER}'@'%' IDENTIFIED BY '${MAUTIC_DB_PASSWORD}';
|
|
ALTER USER '${MAUTIC_DB_USER}'@'%' IDENTIFIED BY '${MAUTIC_DB_PASSWORD}';
|
|
GRANT ALL PRIVILEGES ON \`${MAUTIC_DB_NAME}\`.* TO '${MAUTIC_DB_USER}'@'%';
|
|
FLUSH PRIVILEGES;
|
|
SQL
|
|
|
|
echo "OK: MariaDB User/DB/PW angeglichen."
|
|
|
|
echo
|
|
echo "[4] hxki-web: repariere Service-Definition aus vorhandenem Backup (damit /app/package.json wieder stimmt)"
|
|
|
|
# Quelle suchen (du hast welche gefunden)
|
|
SRC=""
|
|
for cand in \
|
|
/opt/hx-ki/com-stack/docker-compose.yml \
|
|
/opt/hx-ki/com-stack/docker-compose.yml.bak.* \
|
|
/opt/hx-ki/docker/docker-compose.yml.bak_* \
|
|
/opt/hx-ki/com2-stack/docker-compose.yml.bak.* ; do
|
|
for f in $cand; do
|
|
[ -f "$f" ] || continue
|
|
if grep -qE '^[[:space:]]{2}hxki-web:[[:space:]]*$' "$f"; then
|
|
SRC="$f"
|
|
break 2
|
|
fi
|
|
done
|
|
done
|
|
|
|
if [ -z "$SRC" ]; then
|
|
echo "WARN: Keine Quelle mit hxki-web gefunden -> überspringe web-restore."
|
|
else
|
|
echo "SRC(web)=$SRC"
|
|
cp -a "$SRC" "$BK/docker-compose.yml.web-src"
|
|
python3 - <<PY
|
|
import re
|
|
from pathlib import Path
|
|
|
|
dst = Path("$F")
|
|
src = Path("$SRC")
|
|
|
|
d = dst.read_text()
|
|
s = src.read_text()
|
|
|
|
def extract_block(text, name):
|
|
# block: " name:" bis zum nächsten " <service>:"
|
|
m = re.search(rf'(?ms)^\\s{{2}}{re.escape(name)}:\\s*\\n.*?(?=^\\s{{2}}[A-Za-z0-9_.-]+:\\s*$|\\Z)', text)
|
|
return m.group(0) if m else None
|
|
|
|
web = extract_block(s, "hxki-web")
|
|
if not web:
|
|
raise SystemExit("SRC hat keinen hxki-web Block obwohl grep ihn fand (unerwartet).")
|
|
|
|
# dst services-block finden
|
|
ms = re.search(r'(?ms)^services:\\s*\\n', d)
|
|
if not ms:
|
|
raise SystemExit("DST hat keinen top-level services:-Block.")
|
|
|
|
# wenn dst schon hxki-web hat -> ersetzen, sonst einfügen
|
|
if re.search(r'(?m)^\\s{2}hxki-web:\\s*$', d):
|
|
d2 = re.sub(r'(?ms)^\\s{2}hxki-web:\\s*\\n.*?(?=^\\s{2}[A-Za-z0-9_.-]+:\\s*$|\\Z)', web, d)
|
|
else:
|
|
# nach services: direkt einfügen (oben)
|
|
d2 = re.sub(r'(?ms)^(services:\\s*\\n)', r'\\1' + web + "\\n", d, count=1)
|
|
|
|
# sicherstellen, dass hxki-web im hxki-internal hängt (wenn nicht, adden)
|
|
if "hxki-web:" in d2 and "networks: [hxki-internal]" not in web and "networks:" not in web:
|
|
# falls web-block gar keine networks hat: am Ende des blocks ergänzen
|
|
d2 = re.sub(r'(?ms)(^\\s{2}hxki-web:\\s*\\n.*?)(?=^\\s{2}[A-Za-z0-9_.-]+:\\s*$|\\Z)',
|
|
lambda m: m.group(1).rstrip()+"\\n networks: [hxki-internal]\\n",
|
|
d2, count=1)
|
|
|
|
dst.write_text(d2)
|
|
PY
|
|
echo "OK: hxki-web Block restored/patched."
|
|
fi
|
|
|
|
echo
|
|
echo "[5] Validate + Restart Orchester"
|
|
cd "$DIR"
|
|
docker compose -f "$F" config >/dev/null
|
|
docker compose down --remove-orphans
|
|
docker compose up -d --remove-orphans
|
|
|
|
echo
|
|
echo "[6] Hard Checks"
|
|
docker ps --format 'NAME={{.Names}} STATUS={{.Status}} PORTS={{.Ports}}' | egrep 'hxki-|hx-caddy' || true
|
|
docker network inspect "$NET" --format '{{range $id,$c := .Containers}}{{println $c.Name}}{{end}}' | sort
|
|
|
|
echo
|
|
echo "[7] Caddy -> Upstreams"
|
|
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
|
|
docker exec -it hx-caddy sh -lc 'wget -qO- http://hxki-mautic/ >/dev/null && echo OK_CADDY_TO_MAUTIC || echo FAIL_CADDY_TO_MAUTIC' || true
|
|
# web: probiere 80 und 3000
|
|
docker exec -it hx-caddy sh -lc '(wget -qO- http://hxki-web/ >/dev/null && echo OK_CADDY_TO_WEB_80) || (wget -qO- http://hxki-web:3000/ >/dev/null && echo OK_CADDY_TO_WEB_3000) || echo FAIL_CADDY_TO_WEB' || true
|
|
|
|
echo
|
|
echo "[8] Logs kurz"
|
|
docker logs --tail=30 hxki-n8n 2>&1 || true
|
|
docker logs --tail=30 hxki-mautic 2>&1 || true
|
|
docker logs --tail=30 hxki-web 2>&1 || true
|
|
|
|
echo "=== ENDE ==="
|