initial COM2 system snapshot
This commit is contained in:
232
COM2_DB_BINDMOUNT_RECOVER_AND_FIX_ONE_SHOT.sh
Executable file
232
COM2_DB_BINDMOUNT_RECOVER_AND_FIX_ONE_SHOT.sh
Executable file
@@ -0,0 +1,232 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
# === Autorität ===
|
||||
COMPOSE_DIR="/opt/hx-ki/com2-stack"
|
||||
COMPOSE_FILE="${COMPOSE_DIR}/docker-compose.yml"
|
||||
ENV_FILE="${COMPOSE_DIR}/.env"
|
||||
|
||||
# Bind-Mount Pfade (IST-Zustand, von dir geliefert)
|
||||
PG_BIND="/opt/hx-ki/postgres"
|
||||
MY_BIND="/opt/hx-ki/mautic/db"
|
||||
|
||||
# Container-Namen (IST)
|
||||
PG_C="hxki-postgres"
|
||||
MY_C="hxki-mariadb"
|
||||
|
||||
TS="$(date +%Y%m%d-%H%M%S)"
|
||||
BK_DIR="/opt/hx-ki/backups/com2-one-shot-${TS}"
|
||||
mkdir -p "$BK_DIR"
|
||||
|
||||
echo "=== COM2 ONE-SHOT · RECOVER + FIX (no guessing) ==="
|
||||
echo "Compose: $COMPOSE_FILE"
|
||||
echo "Env: $ENV_FILE"
|
||||
echo "Backup: $BK_DIR"
|
||||
echo
|
||||
|
||||
# --- Preconditions ---
|
||||
[ -f "$COMPOSE_FILE" ] || { echo "FAIL: FEHLT $COMPOSE_FILE"; exit 1; }
|
||||
[ -d "$PG_BIND" ] || { echo "FAIL: FEHLT Postgres Bind $PG_BIND"; exit 1; }
|
||||
[ -d "$MY_BIND" ] || { echo "FAIL: FEHLT MariaDB Bind $MY_BIND"; exit 1; }
|
||||
|
||||
cp -a "$COMPOSE_FILE" "$BK_DIR/docker-compose.yml.bak"
|
||||
[ -f "$ENV_FILE" ] && cp -a "$ENV_FILE" "$BK_DIR/.env.bak" || true
|
||||
|
||||
# --- Helper: finde letzte echte Secrets (ohne CHANGE_ME) ---
|
||||
find_last_secret() {
|
||||
local key="$1"
|
||||
local base="/opt/hx-ki"
|
||||
# Suche in .env / compose / backups
|
||||
# Priorität: neueste Datei gewinnt
|
||||
local hit
|
||||
hit="$(find "$base" -maxdepth 6 -type f \
|
||||
\( -iname ".env" -o -iname "*.env" -o -iname "docker-compose*.yml" -o -iname "*.bak*" -o -iname "*.yml" \) \
|
||||
-printf '%T@ %p\n' 2>/dev/null \
|
||||
| sort -nr \
|
||||
| awk '{print $2}' \
|
||||
| while read -r f; do
|
||||
# KEY=VALUE Zeile
|
||||
if grep -qE "^${key}=" "$f" 2>/dev/null; then
|
||||
v="$(grep -E "^${key}=" "$f" | tail -n 1 | cut -d= -f2- | tr -d '\r')"
|
||||
# skip empty / placeholder
|
||||
if [ -n "$v" ] && ! echo "$v" | grep -qiE 'CHANGE_ME|CHANGEME|changeme|__REPLACE__'; then
|
||||
echo "$v"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
done)" || true
|
||||
echo "$hit"
|
||||
}
|
||||
|
||||
# --- 1) ENV befüllen aus altem Zustand (nur wenn gefunden) ---
|
||||
echo "[1] Recover Secrets aus /opt/hx-ki (no guessing)"
|
||||
PG_PASSWORD="$(find_last_secret "PG_PASSWORD")"
|
||||
MARIADB_ROOT_PASSWORD="$(find_last_secret "MARIADB_ROOT_PASSWORD")"
|
||||
MAUTIC_DB_PASSWORD="$(find_last_secret "MAUTIC_DB_PASSWORD")"
|
||||
|
||||
# Optional Defaults (nur wenn vorhanden)
|
||||
PG_USER="$(find_last_secret "PG_USER")"; PG_USER="${PG_USER:-hxki}"
|
||||
PG_DB="$(find_last_secret "PG_DB")"; PG_DB="${PG_DB:-n8n}"
|
||||
|
||||
MAUTIC_DB_USER="$(find_last_secret "MAUTIC_DB_USER")"; MAUTIC_DB_USER="${MAUTIC_DB_USER:-mautic}"
|
||||
MAUTIC_DB_NAME="$(find_last_secret "MAUTIC_DB_NAME")"; MAUTIC_DB_NAME="${MAUTIC_DB_NAME:-mautic}"
|
||||
|
||||
# N8N Host/Proto (optional)
|
||||
N8N_HOST="$(find_last_secret "N8N_HOST")"; N8N_HOST="${N8N_HOST:-n8n.hx-ki.com}"
|
||||
N8N_PROTOCOL="$(find_last_secret "N8N_PROTOCOL")"; N8N_PROTOCOL="${N8N_PROTOCOL:-https}"
|
||||
|
||||
missing=0
|
||||
[ -n "$PG_PASSWORD" ] || { echo "FAIL: PG_PASSWORD nicht gefunden (alter Zustand fehlt)"; missing=1; }
|
||||
[ -n "$MARIADB_ROOT_PASSWORD" ] || { echo "FAIL: MARIADB_ROOT_PASSWORD nicht gefunden (alter Zustand fehlt)"; missing=1; }
|
||||
[ -n "$MAUTIC_DB_PASSWORD" ] || { echo "FAIL: MAUTIC_DB_PASSWORD nicht gefunden (alter Zustand fehlt)"; missing=1; }
|
||||
|
||||
if [ "$missing" -ne 0 ]; then
|
||||
echo
|
||||
echo "STOP: Ich rate keine Passwörter."
|
||||
echo "Gib mir die alten Values oder lege die alte .env Datei in /opt/hx-ki/ ab."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cat > "$ENV_FILE" <<ENV
|
||||
PG_USER=${PG_USER}
|
||||
PG_PASSWORD=${PG_PASSWORD}
|
||||
PG_DB=${PG_DB}
|
||||
|
||||
MARIADB_ROOT_PASSWORD=${MARIADB_ROOT_PASSWORD}
|
||||
MAUTIC_DB_USER=${MAUTIC_DB_USER}
|
||||
MAUTIC_DB_PASSWORD=${MAUTIC_DB_PASSWORD}
|
||||
MAUTIC_DB_NAME=${MAUTIC_DB_NAME}
|
||||
|
||||
N8N_HOST=${N8N_HOST}
|
||||
N8N_PROTOCOL=${N8N_PROTOCOL}
|
||||
ENV
|
||||
|
||||
echo "OK: .env konsistent aus altem Zustand gesetzt."
|
||||
echo
|
||||
|
||||
# --- 2) Stack runter (sauber) ---
|
||||
echo "[2] Orchester down"
|
||||
cd "$COMPOSE_DIR"
|
||||
docker compose down --remove-orphans || true
|
||||
|
||||
# --- 3) Postgres: PW + DB fix via temporär trust (bind-mount pg_hba.conf) ---
|
||||
echo "[3] Postgres Repair (bind-mount, deterministisch)"
|
||||
|
||||
PG_HBA="${PG_BIND}/pg_hba.conf"
|
||||
[ -f "$PG_HBA" ] || { echo "FAIL: FEHLT $PG_HBA"; exit 1; }
|
||||
|
||||
cp -a "$PG_HBA" "$BK_DIR/pg_hba.conf.bak"
|
||||
|
||||
# Setze ALLE host/local auf trust (temporär), damit wir ohne Passwort reinkommen
|
||||
# Danach setzen wir wieder auf scram-sha-256 zurück.
|
||||
python3 - <<'PY'
|
||||
from pathlib import Path
|
||||
p = Path("/opt/hx-ki/postgres/pg_hba.conf")
|
||||
s = p.read_text()
|
||||
out=[]
|
||||
for line in s.splitlines():
|
||||
if line.strip().startswith("#") or line.strip()=="":
|
||||
out.append(line); continue
|
||||
parts=line.split()
|
||||
if len(parts)>=5 and parts[0] in ("local","host","hostssl","hostnossl"):
|
||||
# method ist letztes token
|
||||
parts[-1]="trust"
|
||||
out.append(" ".join(parts))
|
||||
else:
|
||||
out.append(line)
|
||||
p.write_text("\n".join(out)+ "\n")
|
||||
PY
|
||||
|
||||
# Starte nur Postgres
|
||||
docker compose up -d "$PG_C"
|
||||
|
||||
# Warten bis Postgres bereit
|
||||
for i in $(seq 1 60); do
|
||||
if docker exec -i "$PG_C" sh -lc "pg_isready -U '$PG_USER' -d postgres >/dev/null 2>&1"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Setze Passwort + DB erstellen (wenn fehlt)
|
||||
docker exec -i "$PG_C" sh -lc "
|
||||
psql -U '$PG_USER' -d postgres -v ON_ERROR_STOP=1 <<SQL
|
||||
DO \$\$
|
||||
BEGIN
|
||||
IF NOT EXISTS (SELECT 1 FROM pg_database WHERE datname='${PG_DB}') THEN
|
||||
CREATE DATABASE \"${PG_DB}\";
|
||||
END IF;
|
||||
END
|
||||
\$\$;
|
||||
ALTER ROLE \"${PG_USER}\" WITH PASSWORD '${PG_PASSWORD}';
|
||||
SQL
|
||||
"
|
||||
|
||||
# Restore pg_hba.conf (Original wiederherstellen)
|
||||
cp -a "$BK_DIR/pg_hba.conf.bak" "$PG_HBA"
|
||||
|
||||
# Restart Postgres (scram wieder aktiv)
|
||||
docker compose restart "$PG_C"
|
||||
echo "OK: Postgres repaired (PW + DB) und auth wieder wie vorher."
|
||||
echo
|
||||
|
||||
# --- 4) MariaDB: root + mautic-user fix via temporary skip-grant-tables ---
|
||||
echo "[4] MariaDB Repair (bind-mount, deterministisch)"
|
||||
|
||||
# Stop mariadb, starte temporär mit skip-grant-tables (nur lokal im container)
|
||||
docker compose stop "$MY_C" || true
|
||||
|
||||
TMP_C="hxki-mariadb-repair-${TS}"
|
||||
# gleicher bind mount, aber ohne Auth
|
||||
docker run -d --rm \
|
||||
--name "$TMP_C" \
|
||||
-v "${MY_BIND}:/var/lib/mysql" \
|
||||
--network none \
|
||||
mariadb:latest \
|
||||
--skip-grant-tables --skip-networking
|
||||
|
||||
# warten bis mysqld da ist
|
||||
for i in $(seq 1 60); do
|
||||
if docker exec -i "$TMP_C" sh -lc "mysqladmin ping --silent >/dev/null 2>&1"; then
|
||||
break
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
|
||||
# Set root pw + mautic user + db
|
||||
docker exec -i "$TMP_C" sh -lc "
|
||||
mysql -uroot <<SQL
|
||||
FLUSH PRIVILEGES;
|
||||
ALTER USER 'root'@'localhost' 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}';
|
||||
GRANT ALL PRIVILEGES ON \`${MAUTIC_DB_NAME}\`.* TO '${MAUTIC_DB_USER}'@'%';
|
||||
FLUSH PRIVILEGES;
|
||||
SQL
|
||||
"
|
||||
|
||||
docker stop "$TMP_C" >/dev/null
|
||||
|
||||
# normal wieder hoch
|
||||
docker compose up -d "$MY_C"
|
||||
echo "OK: MariaDB repaired (root + mautic user/db)."
|
||||
echo
|
||||
|
||||
# --- 5) Full stack up + checks ---
|
||||
echo "[5] Orchester up"
|
||||
docker compose up -d --remove-orphans
|
||||
|
||||
echo
|
||||
echo "=== STATUS ==="
|
||||
docker ps --format 'NAME={{.Names}} STATUS={{.Status}} PORTS={{.Ports}}' | egrep 'hxki-|hx-caddy' || true
|
||||
|
||||
echo
|
||||
echo "=== CHECKS (DB auth) ==="
|
||||
echo "[A] n8n logs (tail 20)"
|
||||
docker logs --tail=20 hxki-n8n || true
|
||||
echo
|
||||
echo "[B] mautic logs (tail 20)"
|
||||
docker logs --tail=20 hxki-mautic || true
|
||||
|
||||
echo
|
||||
echo "=== ENDE · ONE-SHOT ==="
|
||||
Reference in New Issue
Block a user