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

160 lines
5.4 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
DIR="/opt/hx-ki/com2-stack"
COMPOSE="$DIR/docker-compose.yml"
ENVF="$DIR/.env"
[ -f "$COMPOSE" ] || { echo "FAIL: missing $COMPOSE"; exit 1; }
[ -f "$ENVF" ] || { echo "FAIL: missing $ENVF"; exit 1; }
cd "$DIR"
echo "=== COM2 · MAUTIC INSTALL (ONE-SHOT, NO REBUILD, NO GUESSING) ==="
# Load .env as authority (only simple KEY=VALUE lines)
set -a
. "$ENVF"
set +a
# Resolve service names from compose (authority: compose)
MAUTIC_SVC="$(python3 - <<'PY'
import re, pathlib
p=pathlib.Path("/opt/hx-ki/com2-stack/docker-compose.yml")
s=p.read_text()
m=re.search(r'(?ms)^services:\s*\n(.*?)(?=^\S|\Z)', s)
if not m: raise SystemExit("FAIL: no services: block")
blk=m.group(1)
# find service with container_name: hxki-mautic
cur=None
for line in blk.splitlines():
mm=re.match(r'^\s{2}([A-Za-z0-9_.-]+):\s*$', line)
if mm: cur=mm.group(1); continue
if cur and re.match(r'^\s{4}container_name:\s*hxki-mautic\s*$', line):
print(cur); raise SystemExit(0)
raise SystemExit("FAIL: could not find service for container_name: hxki-mautic")
PY
)"
DB_SVC="$(python3 - <<'PY'
import re, pathlib
p=pathlib.Path("/opt/hx-ki/com2-stack/docker-compose.yml")
s=p.read_text()
m=re.search(r'(?ms)^services:\s*\n(.*?)(?=^\S|\Z)', s)
if not m: raise SystemExit("FAIL: no services: block")
blk=m.group(1)
# find service with container_name: hxki-mariadb
cur=None
for line in blk.splitlines():
mm=re.match(r'^\s{2}([A-Za-z0-9_.-]+):\s*$', line)
if mm: cur=mm.group(1); continue
if cur and re.match(r'^\s{4}container_name:\s*hxki-mariadb\s*$', line):
print(cur); raise SystemExit(0)
raise SystemExit("FAIL: could not find service for container_name: hxki-mariadb")
PY
)"
MA="hxki-mautic"
MY="hxki-mariadb"
CA="hx-caddy"
echo "[1] Bring up DB + Mautic (no orphans change)"
docker compose up -d "$DB_SVC" "$MAUTIC_SVC" >/dev/null
echo "[2] Hard requirements from .env (NO guessing)"
req() { local k="$1"; [ -n "${!k:-}" ] || { echo "FAIL: missing $k in $ENVF"; exit 1; }; }
req MAUTIC_DB_HOST
req MAUTIC_DB_NAME
req MAUTIC_DB_USER
req MAUTIC_DB_PASSWORD
req MAUTIC_ADMIN_USERNAME
req MAUTIC_ADMIN_PASSWORD
req MAUTIC_ADMIN_EMAIL
echo " DB_HOST=$MAUTIC_DB_HOST DB_NAME=$MAUTIC_DB_NAME DB_USER=$MAUTIC_DB_USER DB_PASS=***"
echo " ADMIN_USER=$MAUTIC_ADMIN_USERNAME ADMIN_EMAIL=$MAUTIC_ADMIN_EMAIL ADMIN_PASS=***"
echo "[3] Read MariaDB root password (NO guessing: container env)"
ROOTPW="$(docker inspect "$MY" --format '{{range .Config.Env}}{{println .}}{{end}}' \
| awk -F= '/^(MARIADB_ROOT_PASSWORD|MYSQL_ROOT_PASSWORD)=/{print $2}' | tail -n1 || true)"
[ -n "${ROOTPW:-}" ] || { echo "FAIL: MariaDB root password not found in container env"; exit 1; }
echo "[4] Wait MariaDB ready (max 60s) + ensure DB exists (no data loss)"
for i in {1..60}; do
if docker exec -i "$MY" sh -lc "mariadb -uroot -p\"$ROOTPW\" -e 'SELECT 1' >/dev/null 2>&1"; then
break
fi
sleep 1
[ "$i" -eq 60 ] && { echo "FAIL: MariaDB not ready"; docker logs --tail=120 "$MY" || true; exit 1; }
done
docker exec -i "$MY" sh -lc "mariadb -uroot -p\"$ROOTPW\" <<SQL
CREATE DATABASE IF NOT EXISTS \\\`$MAUTIC_DB_NAME\\\`;
SQL" >/dev/null
# If Mautic uses non-root user, ensure it can log in + has grants (still no data loss)
if [ "$MAUTIC_DB_USER" != "root" ]; then
docker exec -i "$MY" sh -lc "mariadb -uroot -p\"$ROOTPW\" <<SQL
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" >/dev/null
fi
echo "[5] If already installed -> stop here (local.php present)"
if docker exec -i "$MA" sh -lc "test -f app/config/local.php"; then
echo "OK: already installed (app/config/local.php exists)"
else
echo "[6] Run Mautic installer inside container (deterministic CLI)"
# detect console path
CONSOLE=""
if docker exec -i "$MA" sh -lc "test -x bin/console"; then
CONSOLE="bin/console"
elif docker exec -i "$MA" sh -lc "test -x app/console"; then
CONSOLE="app/console"
else
echo "FAIL: cannot find bin/console or app/console inside $MA"
docker exec -i "$MA" sh -lc "ls -la" || true
exit 1
fi
# Run installer (no interaction)
docker exec -i "$MA" sh -lc "
php $CONSOLE mautic:install \
--db_driver=pdo_mysql \
--db_host=\"$MAUTIC_DB_HOST\" \
--db_port=3306 \
--db_name=\"$MAUTIC_DB_NAME\" \
--db_user=\"$MAUTIC_DB_USER\" \
--db_password=\"$MAUTIC_DB_PASSWORD\" \
--admin_firstname=HXKI \
--admin_lastname=Admin \
--admin_username=\"$MAUTIC_ADMIN_USERNAME\" \
--admin_password=\"$MAUTIC_ADMIN_PASSWORD\" \
--admin_email=\"$MAUTIC_ADMIN_EMAIL\" \
--no-interaction
" || { echo "FAIL: mautic:install failed"; docker logs --tail=200 "$MA" || true; exit 1; }
echo "[7] Verify local.php created"
docker exec -i "$MA" sh -lc "test -f app/config/local.php" || { echo "FAIL: install did not create app/config/local.php"; exit 1; }
echo "OK: installed (local.php present)"
fi
echo "[8] Restart Mautic (clean) and verify Caddy can reach it"
docker compose up -d --force-recreate "$MAUTIC_SVC" >/dev/null
# wait for http from caddy
for i in {1..60}; do
if docker exec -i "$CA" sh -lc "wget -qO- http://$MA/ >/dev/null"; then
echo "OK_CADDY_TO_MAUTIC"
echo "=== DONE ==="
exit 0
fi
sleep 1
done
echo "FAIL: Caddy still cannot reach Mautic after install"
docker logs --tail=200 "$MA" || true
exit 1