initial COM2 system snapshot

This commit is contained in:
gitea
2026-03-06 15:22:40 +00:00
commit 9c0fa49baf
4377 changed files with 273033 additions and 0 deletions

218
COM2_DB_ALIGN_ONE_SHOT.sh Executable file
View File

@@ -0,0 +1,218 @@
#!/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