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

219 lines
7.0 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"
ENVF="$DIR/.env"
NET="hxki-internal"
TS="$(date +%Y%m%d-%H%M%S)"
BKDIR="/opt/hx-ki/backups/com2-db-align-$TS"
mkdir -p "$BKDIR"
echo "=== COM2 DB ALIGN (one-shot) ==="
echo "Compose: $F"
echo "Env: $ENVF"
echo "Backup: $BKDIR"
[ -f "$F" ] || { echo "FEHLT: $F"; exit 1; }
[ -f "$ENVF" ] || { echo "FEHLT: $ENVF"; exit 1; }
cp -a "$F" "$BKDIR/docker-compose.yml"
cp -a "$ENVF" "$BKDIR/.env"
# Netzwerk muss existieren (external)
docker network inspect "$NET" >/dev/null 2>&1 || docker network create "$NET" >/dev/null
# --- .env laden (ohne zu crashen wenn Leerzeilen/Kommentare) ---
set -a
# shellcheck disable=SC1090
source <(grep -v '^\s*#' "$ENVF" | sed '/^\s*$/d')
set +a
need_real_pw() {
local k="$1"; local v="${!k:-}"
if [[ -z "$v" || "$v" =~ CHANGE_ME|CHANGEME|changeme ]]; then return 0; fi
return 1
}
echo
echo "[0] Secrets prüfen (keine Platzhalter erlaubt)"
if need_real_pw PG_PASSWORD || need_real_pw MARIADB_ROOT_PASSWORD || need_real_pw MAUTIC_DB_PASSWORD; then
echo "WARN: In $ENVF sind Platzhalter/fehlende Werte."
echo " Ich frage jetzt EINMAL nach echten Passwörtern und schreibe sie nach $ENVF."
echo
if need_real_pw PG_PASSWORD; then
read -r -s -p "PG_PASSWORD (für Postgres User hxki): " PG_PASSWORD; echo
fi
if need_real_pw MARIADB_ROOT_PASSWORD; then
read -r -s -p "MARIADB_ROOT_PASSWORD (neues Root-PW für MariaDB): " MARIADB_ROOT_PASSWORD; echo
fi
if need_real_pw MAUTIC_DB_PASSWORD; then
read -r -s -p "MAUTIC_DB_PASSWORD (für MariaDB User mautic): " MAUTIC_DB_PASSWORD; echo
fi
# Minimaler .env Patch (nur Keys, die wir brauchen)
# Backup ist schon in BKDIR.
awk -v pg="$PG_PASSWORD" -v mr="$MARIADB_ROOT_PASSWORD" -v mp="$MAUTIC_DB_PASSWORD" '
BEGIN{done_pg=done_mr=done_mp=0}
/^PG_PASSWORD=/{print "PG_PASSWORD="pg; done_pg=1; next}
/^MARIADB_ROOT_PASSWORD=/{print "MARIADB_ROOT_PASSWORD="mr; done_mr=1; next}
/^MAUTIC_DB_PASSWORD=/{print "MAUTIC_DB_PASSWORD="mp; done_mp=1; next}
{print}
END{
if(!done_pg) print "PG_PASSWORD="pg
if(!done_mr) print "MARIADB_ROOT_PASSWORD="mr
if(!done_mp) print "MAUTIC_DB_PASSWORD="mp
}
' "$ENVF" > "$ENVF.tmp" && mv "$ENVF.tmp" "$ENVF"
echo "OK: $ENVF aktualisiert (Backup: $BKDIR/.env)"
fi
# Reload .env after potential patch
set -a
# shellcheck disable=SC1090
source <(grep -v '^\s*#' "$ENVF" | sed '/^\s*$/d')
set +a
: "${PG_USER:=hxki}"
: "${PG_DB:=n8n}"
: "${MAUTIC_DB_USER:=mautic}"
: "${MAUTIC_DB_NAME:=mautic}"
echo
echo "[1] Orchester: sicher hoch (damit DB-Container laufen)"
cd "$DIR"
docker compose up -d --remove-orphans
echo
echo "[2] POSTGRES align (User+DB+PW) Volume bleibt"
# Wir gehen als postgres-OS-User rein (nicht als DB-User), damit kein Passwort-Raten nötig ist.
docker exec -u postgres -i hxki-postgres psql -d postgres <<SQL
DO \$\$
BEGIN
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = '${PG_USER}') THEN
CREATE ROLE ${PG_USER} LOGIN;
END IF;
ALTER ROLE ${PG_USER} WITH PASSWORD '${PG_PASSWORD}';
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname = '${PG_DB}') THEN
CREATE DATABASE ${PG_DB} OWNER ${PG_USER};
END IF;
END
\$\$;
SQL
echo "OK: Postgres User/DB/PW aligned: ${PG_USER}/${PG_DB}"
echo
echo "[3] MARIADB Root-Reset (Recovery-Container) + Mautic User/DB fix Volume bleibt"
# Volume/Bind für /var/lib/mysql ermitteln
MOUNT_SRC="$(docker inspect hxki-mariadb --format '{{range .Mounts}}{{if eq .Destination "/var/lib/mysql"}}{{.Source}}{{end}}{{end}}')"
MOUNT_NAME="$(docker inspect hxki-mariadb --format '{{range .Mounts}}{{if eq .Destination "/var/lib/mysql"}}{{.Name}}{{end}}{{end}}')"
IMG="$(docker inspect hxki-mariadb --format '{{.Config.Image}}')"
if [[ -n "$MOUNT_NAME" ]]; then
VOLARG="-v ${MOUNT_NAME}:/var/lib/mysql"
elif [[ -n "$MOUNT_SRC" ]]; then
VOLARG="-v ${MOUNT_SRC}:/var/lib/mysql"
else
echo "FAIL: Konnte MariaDB /var/lib/mysql Mount nicht ermitteln."
exit 1
fi
# Mautic stoppen damit es nicht dauernd hämmert
docker stop hxki-mautic >/dev/null 2>&1 || true
# MariaDB stoppen (damit Volume frei ist)
docker stop hxki-mariadb >/dev/null 2>&1 || true
# Recovery-Container starten (ohne Grants, ohne Network)
docker rm -f hxki-mariadb-recover >/dev/null 2>&1 || true
docker run -d --name hxki-mariadb-recover $VOLARG --entrypoint mysqld "$IMG" \
--skip-grant-tables --skip-networking --socket=/tmp/mysqld.sock >/dev/null
# Warten bis Socket da ist
for i in {1..40}; do
if docker exec hxki-mariadb-recover sh -lc 'test -S /tmp/mysqld.sock'; then break; fi
sleep 0.25
done
docker exec hxki-mariadb-recover sh -lc 'test -S /tmp/mysqld.sock' || { echo "FAIL: MariaDB recover socket nicht bereit"; docker logs --tail=80 hxki-mariadb-recover; exit 1; }
# Root-PW setzen + Mautic DB/User fixen
docker exec -i hxki-mariadb-recover sh -lc "mariadb --protocol=socket -uroot -S /tmp/mysqld.sock" <<SQL
FLUSH PRIVILEGES;
ALTER USER IF EXISTS 'root'@'localhost' IDENTIFIED BY '${MARIADB_ROOT_PASSWORD}';
ALTER USER IF EXISTS 'root'@'%' IDENTIFIED BY '${MARIADB_ROOT_PASSWORD}';
CREATE DATABASE IF NOT EXISTS ${MAUTIC_DB_NAME};
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
# Recovery runter
docker rm -f hxki-mariadb-recover >/dev/null
# MariaDB wieder hoch über Compose (mit NEUEM Root-PW in .env)
cd "$DIR"
docker compose up -d --remove-orphans hxki-mariadb
# kurz warten
sleep 2
# Mautic wieder hoch
docker compose up -d --remove-orphans hxki-mautic
echo "OK: MariaDB Root-PW + Mautic DB/User aligned."
echo
echo "[4] Services neu hoch (n8n/web/caddy) und harte Checks"
docker compose up -d --remove-orphans
echo
echo "[A] Container Status"
docker ps --format 'NAME={{.Names}} STATUS={{.Status}} PORTS={{.Ports}}' | egrep 'hxki-|hx-caddy' || true
echo
echo "[B] Netzwerk-Mitglieder ($NET)"
docker network inspect "$NET" --format '{{range $id,$c := .Containers}}{{println $c.Name}}{{end}}' | sort
echo
echo "[C] Caddy -> Upstreams (intern, 10s Retry)"
check_up() {
local name="$1" url="$2"
for i in {1..20}; do
if docker exec hx-caddy sh -lc "wget -qO- '$url' >/dev/null 2>&1"; then
echo "OK_CADDY_TO_${name}"
return 0
fi
sleep 0.5
done
echo "FAIL_CADDY_TO_${name}"
return 1
}
FAIL=0
check_up WEB "http://hxki-web:3000/" || FAIL=1
check_up N8N "http://hxki-n8n:5678/" || FAIL=1
check_up MAUTIC "http://hxki-mautic:80/" || FAIL=1
echo
echo "[D] Logs (kurz)"
echo "--- n8n ---"
docker logs --tail=40 hxki-n8n || true
echo "--- mautic ---"
docker logs --tail=40 hxki-mautic || true
echo "--- web ---"
docker logs --tail=40 hxki-web || true
echo "--- caddy ---"
docker logs --tail=40 hx-caddy || true
echo
if [[ "$FAIL" -eq 0 ]]; then
echo "=== OK: COM2 ist wieder stabil (DBs aligned, Upstreams erreichbar) ==="
else
echo "=== WARN: DBs aligned, aber mind. ein Upstream ist noch nicht erreichbar (siehe FAIL_*) ==="
echo "Backup liegt hier: $BKDIR"
fi