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

258
COM2_FERRARI_REPAIR_ONE_SHOT.sh Executable file
View File

@@ -0,0 +1,258 @@
#!/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="/opt/hx-ki/backups/com2-ferrari-$TS"
mkdir -p "$BK"
echo "=== COM2 · FERRARI REPAIR ONE-SHOT (no guessing) ==="
echo "Compose: $F"
echo "Env: $ENVF"
echo "Backup: $BK"
echo
[ -f "$F" ] || { echo "FAIL: FEHLT $F"; exit 1; }
cp -a "$F" "$BK/docker-compose.yml.pre" || true
[ -f "$ENVF" ] && cp -a "$ENVF" "$BK/.env.pre" || true
# --- helpers ---------------------------------------------------------------
die(){ echo "FAIL: $*" ; exit 1; }
# find candidates from many places, newest first
collect_kv_candidates() {
local key="$1"
# search in .env files + compose backups + docker-compose.yml* (only small grep)
find /opt/hx-ki -maxdepth 6 -type f \
\( -iname ".env" -o -iname "*.env" -o -iname "docker-compose*.yml" -o -iname "docker-compose*.yml.*" -o -iname "*.yml.bak*" \) \
-printf "%T@ %p\n" 2>/dev/null | sort -nr | awk '{ $1=""; sub(/^ /,""); print }' |
while read -r p; do
[ -f "$p" ] || continue
# exact KEY=VALUE lines only
awk -v k="$key" -F= '
$1==k {
v=$0; sub(/^[^=]+= /,"",v); sub(/^[^=]+=/,"",v);
gsub(/\r/,"",v);
if (v!="" && v !~ /CHANGE_ME|CHANGEME|changeme/) { print v }
}' "$p" 2>/dev/null | head -n 5
done | awk 'NF' | awk '!seen[$0]++' | head -n 30
}
ensure_net() {
docker network inspect "$NET" >/dev/null 2>&1 || docker network create "$NET" >/dev/null
}
stop_host_caddy() {
if systemctl is-active --quiet caddy 2>/dev/null; then
echo "[0] Stoppe host-caddy (systemd) Ports 80/443 frei"
systemctl stop caddy
fi
}
compose_down() {
cd "$DIR"
docker compose down --remove-orphans || true
}
compose_up() {
cd "$DIR"
docker compose up -d --remove-orphans
}
# Test Postgres password by real connection
pg_try_pw() {
local user="$1" pw="$2"
docker exec -e PGPASSWORD="$pw" hxki-postgres sh -lc "psql -U '$user' -d postgres -tAc 'select 1' >/dev/null 2>&1"
}
# Ensure DB exists (create if missing) using admin user
pg_ensure_db() {
local admin_user="$1" admin_pw="$2" db="$3"
docker exec -e PGPASSWORD="$admin_pw" hxki-postgres sh -lc \
"psql -U '$admin_user' -d postgres -tAc \"select 1 from pg_database where datname='${db}'\" | grep -q 1 || psql -U '$admin_user' -d postgres -c \"create database \\\"${db}\\\"\" >/dev/null"
}
# Ensure role exists + password (only if missing)
pg_ensure_role() {
local admin_user="$1" admin_pw="$2" role="$3" role_pw="$4"
docker exec -e PGPASSWORD="$admin_pw" hxki-postgres sh -lc \
"psql -U '$admin_user' -d postgres -tAc \"select 1 from pg_roles where rolname='${role}'\" | grep -q 1 || psql -U '$admin_user' -d postgres -c \"create role \\\"${role}\\\" login password '${role_pw}'\" >/dev/null"
}
# grant owner if needed
pg_set_owner() {
local admin_user="$1" admin_pw="$2" db="$3" owner="$4"
docker exec -e PGPASSWORD="$admin_pw" hxki-postgres sh -lc \
"psql -U '$admin_user' -d postgres -c \"alter database \\\"${db}\\\" owner to \\\"${owner}\\\"\" >/dev/null 2>&1 || true"
}
# MariaDB root auth test (real)
my_root_try_pw() {
local pw="$1"
docker exec hxki-mariadb sh -lc "mysqladmin ping -uroot -p'$pw' --silent >/dev/null 2>&1"
}
# MariaDB user auth test
my_user_try_pw() {
local user="$1" pw="$2" db="$3"
docker exec hxki-mariadb sh -lc "mysql -u'$user' -p'$pw' -D'$db' -e 'select 1' >/dev/null 2>&1"
}
# Ensure mautic db/user exists (create only if missing; uses root)
my_ensure_mautic() {
local rootpw="$1" db="$2" user="$3" userpw="$4"
docker exec hxki-mariadb sh -lc "
mysql -uroot -p'$rootpw' -e \"CREATE DATABASE IF NOT EXISTS \\\`$db\\\`;\" >/dev/null &&
mysql -uroot -p'$rootpw' -e \"CREATE USER IF NOT EXISTS '$user'@'%' IDENTIFIED BY '$userpw';\" >/dev/null &&
mysql -uroot -p'$rootpw' -e \"GRANT ALL PRIVILEGES ON \\\`$db\\\`.* TO '$user'@'%'; FLUSH PRIVILEGES;\" >/dev/null
"
}
# --- start ---------------------------------------------------------------
[ -d "$DIR" ] || die "FEHLT: $DIR"
stop_host_caddy
ensure_net
echo "[1] Orchester runter (sauber)"
compose_down
echo "[2] Starte NUR DBs (damit wir Credentials echt testen können)"
cd "$DIR"
docker compose up -d hxki-postgres hxki-mariadb || die "DB-Start fehlgeschlagen"
# --- discover postgres admin user (from container env) ----------------------
PG_ADMIN_USER="$(docker inspect hxki-postgres --format '{{range .Config.Env}}{{println .}}{{end}}' | awk -F= '$1=="POSTGRES_USER"{print $2}' | tail -n 1)"
[ -n "$PG_ADMIN_USER" ] || die "POSTGRES_USER nicht gefunden in hxki-postgres Env"
# Candidate passwords from old state
echo "[3] Suche Postgres-Passwort (no guessing: scan + real login test)"
mapfile -t PG_PWS < <(collect_kv_candidates "POSTGRES_PASSWORD")
# also accept PG_PASSWORD style keys
mapfile -t PG_PWS2 < <(collect_kv_candidates "PG_PASSWORD")
PG_PWS+=( "${PG_PWS2[@]}" )
# de-dupe
PG_PWS=( $(printf "%s\n" "${PG_PWS[@]}" | awk 'NF' | awk '!seen[$0]++') )
PG_ADMIN_PW=""
for pw in "${PG_PWS[@]}"; do
if pg_try_pw "$PG_ADMIN_USER" "$pw"; then
PG_ADMIN_PW="$pw"; break
fi
done
[ -n "$PG_ADMIN_PW" ] || die "Kein funktionierendes Postgres-Passwort gefunden (scan+test)."
echo " OK: Postgres auth funktioniert für user=$PG_ADMIN_USER"
# --- discover mariadb root pw ---------------------------------------------
echo "[4] Suche MariaDB root Passwort (scan + real ping test)"
mapfile -t MYROOT_PWS < <(collect_kv_candidates "MARIADB_ROOT_PASSWORD")
mapfile -t MYROOT_PWS2 < <(collect_kv_candidates "MYSQL_ROOT_PASSWORD")
MYROOT_PWS+=( "${MYROOT_PWS2[@]}" )
MYROOT_PWS=( $(printf "%s\n" "${MYROOT_PWS[@]}" | awk 'NF' | awk '!seen[$0]++') )
MY_ROOT_PW=""
for pw in "${MYROOT_PWS[@]}"; do
if my_root_try_pw "$pw"; then
MY_ROOT_PW="$pw"; break
fi
done
[ -n "$MY_ROOT_PW" ] || die "Kein funktionierendes MariaDB root Passwort gefunden (scan+test)."
echo " OK: MariaDB root auth funktioniert"
# --- read target vars from compose/env (but align with OLD secrets) ---------
# Extract current target DB names from compose env placeholders (.env)
# If not present, fall back to container env default
PG_DB="${PG_DB:-}"
PG_USER="${PG_USER:-}"
if [ -f "$ENVF" ]; then
# shellcheck disable=SC1090
set -a; source "$ENVF" 2>/dev/null || true; set +a
fi
# Ensure defaults if env missing
: "${PG_USER:=$PG_ADMIN_USER}"
: "${PG_DB:=n8n}"
# Mautic target vars
: "${MAUTIC_DB_NAME:=mautic}"
: "${MAUTIC_DB_USER:=mautic}"
# try recover MAUTIC_DB_PASSWORD from old state too
mapfile -t MAUTIC_PWS < <(collect_kv_candidates "MAUTIC_DB_PASSWORD")
MAUTIC_DB_PASSWORD="${MAUTIC_DB_PASSWORD:-${MAUTIC_PWS[0]:-}}"
# If not found, we do NOT invent: we only proceed if we can validate, else stop.
if [ -z "${MAUTIC_DB_PASSWORD:-}" ]; then
die "MAUTIC_DB_PASSWORD nicht gefunden im alten Zustand. (Bitte in alten .env/Backups vorhanden machen.)"
fi
echo "[5] Schreibe kanonische .env (nur funktionierende Secrets, kein CHANGE_ME)"
cp -a "$ENVF" "$BK/.env.prewrite" 2>/dev/null || true
cat > "$ENVF" <<ENV
# === CANONICAL (recovered + validated) ===
# Postgres (n8n)
PG_USER=${PG_USER}
PG_PASSWORD=${PG_ADMIN_PW}
PG_DB=${PG_DB}
# Mautic (MariaDB)
MAUTIC_DB_NAME=${MAUTIC_DB_NAME}
MAUTIC_DB_USER=${MAUTIC_DB_USER}
MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
MAUTIC_DB_ROOT_PASSWORD=${MY_ROOT_PW}
# n8n public vars (leave if you already had them in compose via defaults)
N8N_HOST=${N8N_HOST:-localhost}
N8N_PROTOCOL=${N8N_PROTOCOL:-http}
ENV
echo "[6] Postgres: stelle sicher, dass DB für n8n existiert (create only if missing)"
pg_ensure_db "$PG_ADMIN_USER" "$PG_ADMIN_PW" "$PG_DB"
pg_ensure_role "$PG_ADMIN_USER" "$PG_ADMIN_PW" "$PG_USER" "$PG_ADMIN_PW" || true
pg_set_owner "$PG_ADMIN_USER" "$PG_ADMIN_PW" "$PG_DB" "$PG_USER" || true
echo " OK: Postgres DB/Role geprüft"
echo "[7] MariaDB: stelle sicher, dass mautic DB/User passt (create/grant only if needed)"
# if mautic user auth already works, we don't touch grants
if my_user_try_pw "$MAUTIC_DB_USER" "$MAUTIC_DB_PASSWORD" "$MAUTIC_DB_NAME"; then
echo " OK: mautic user auth OK keine Änderungen an MariaDB nötig"
else
echo " INFO: mautic user auth FAIL setze DB/User/Grants deterministisch via root"
my_ensure_mautic "$MY_ROOT_PW" "$MAUTIC_DB_NAME" "$MAUTIC_DB_USER" "$MAUTIC_DB_PASSWORD" || die "MariaDB repair failed"
echo " OK: MariaDB DB/User/Grants gesetzt"
fi
echo "[8] Validate Compose"
cd "$DIR"
docker compose config >/dev/null || die "Compose ist nicht valide."
echo "[9] Orchester hoch"
docker compose up -d --remove-orphans
echo
echo "=== HARD CHECKS (facts) ==="
echo "[A] Container Status"
docker ps --format 'NAME={{.Names}} STATUS={{.Status}} PORTS={{.Ports}}' | egrep 'hxki-|hx-' || true
echo
echo "[B] Logs (tail 30)"
echo "--- hxki-n8n ---"
docker logs --tail=30 hxki-n8n || true
echo "--- hxki-mautic ---"
docker logs --tail=30 hxki-mautic || true
echo "--- hxki-web ---"
docker logs --tail=30 hxki-web || true
echo
echo "[C] Caddy -> Upstreams (internal reachability)"
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
docker exec -it hx-caddy sh -lc 'wget -qO- http://hxki-web/ >/dev/null && echo OK_CADDY_TO_WEB || echo FAIL_CADDY_TO_WEB' || true
echo
echo "=== DONE ==="
echo "Backup: $BK"