#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "$SCRIPT_DIR" DOCKER_CMD=() SECRETS_FILE="$SCRIPT_DIR/.mongo-secrets.env" MONGO_VOLUME_NAME="$(basename "$SCRIPT_DIR" | tr '[:upper:]' '[:lower:]')_mongo_data" ensure_mongo_secrets() { if [ -f "$SECRETS_FILE" ]; then # shellcheck disable=SC1090 source "$SECRETS_FILE" fi if [ -z "${MONGO_INITDB_ROOT_PASSWORD:-}" ]; then MONGO_INITDB_ROOT_PASSWORD="$(openssl rand -hex 24)" fi if [ -z "${MONGO_APP_PASSWORD:-}" ]; then MONGO_APP_PASSWORD="$(openssl rand -hex 24)" fi cat > "$SECRETS_FILE" </dev/null 2>&1; then DOCKER_CMD=(docker) return 0 fi if sudo -n docker info >/dev/null 2>&1; then DOCKER_CMD=(sudo docker) return 0 fi if command -v sudo >/dev/null 2>&1 && [ -t 0 ]; then echo "Docker-Zugriff ohne Gruppe erkannt. Verwende sudo docker (ggf. Passwortabfrage)." if sudo docker info >/dev/null 2>&1; then DOCKER_CMD=(sudo docker) return 0 fi fi echo "[FEHLER] Kein Zugriff auf den Docker Daemon (/var/run/docker.sock)." >&2 echo "Führe das Script mit sudo aus oder füge deinen User zur docker-Gruppe hinzu:" >&2 echo " sudo usermod -aG docker $USER" >&2 echo "Danach neu einloggen und Script erneut starten." >&2 exit 3 } export SESSION_COOKIE_SECURE="0" export INSTANCE_TLS_MODE="development" export INSTANCE_PARENT_DOMAIN="${INSTANCE_PARENT_DOMAIN:-meine-domain}" export DEV_HOSTS_REFRESH_INTERVAL="${DEV_HOSTS_REFRESH_INTERVAL:-30}" echo "Launching WEBSITE stack" echo " SESSION_COOKIE_SECURE=$SESSION_COOKIE_SECURE" echo " INSTANCE_TLS_MODE=$INSTANCE_TLS_MODE" echo " INSTANCE_PARENT_DOMAIN=$INSTANCE_PARENT_DOMAIN" echo " DEV_HOSTS_REFRESH_INTERVAL=$DEV_HOSTS_REFRESH_INTERVAL" ensure_mongo_secrets # Ensure required runtime files exist before building if [ ! -f "$SCRIPT_DIR/gunicorn.conf.py" ]; then echo "[FEHLER] gunicorn.conf.py fehlt in $SCRIPT_DIR. Bitte prüfen." >&2 exit 2 fi resolve_docker_cmd "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" build website mongo_bootstrap_needed() { "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" exec -T mongodb mongosh --quiet --username "$MONGO_INITDB_ROOT_USERNAME" --password "$MONGO_INITDB_ROOT_PASSWORD" --authenticationDatabase admin --eval 'db.adminCommand({ ping: 1 }).ok' >/dev/null 2>&1 } bootstrap_mongo_users() { echo "MongoDB bootstrap erforderlich; starte temporären Recovery-Modus ohne Auth..." "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" stop mongodb || true "${DOCKER_CMD[@]}" run -d --rm \ --name invario-mongo-recovery \ --network host \ -v "${MONGO_VOLUME_NAME}:/data/db" \ mongo:7 \ mongod --dbpath /data/db --bind_ip 127.0.0.1 --port 27017 --noauth >/dev/null trap '"${DOCKER_CMD[@]}" stop invario-mongo-recovery >/dev/null 2>&1 || true' EXIT for _ in 1 2 3 4 5 6 7 8 9 10; do if "${DOCKER_CMD[@]}" run --rm --network host mongo:7 mongosh --quiet mongodb://127.0.0.1:27017 --eval 'db.adminCommand({ ping: 1 }).ok' >/dev/null 2>&1; then break fi sleep 1 done "${DOCKER_CMD[@]}" run --rm --network host --env-file "$SECRETS_FILE" mongo:7 mongosh --quiet mongodb://127.0.0.1:27017 --eval ' const appDatabase = process.env.MONGO_DB_NAME || "Invario_Website"; const rootUser = process.env.MONGO_INITDB_ROOT_USERNAME || "website_root"; const rootPassword = process.env.MONGO_INITDB_ROOT_PASSWORD; const appUser = process.env.MONGO_APP_USER || "website_app"; const appPassword = process.env.MONGO_APP_PASSWORD; if (!rootPassword || !appPassword) { throw new Error("Missing Mongo bootstrap credentials"); } const adminDb = db.getSiblingDB("admin"); try { adminDb.createUser({ user: rootUser, pwd: rootPassword, roles: [{ role: "root", db: "admin" }], }); } catch (error) { if (!String(error).includes("already exists")) { throw error; } } const appDb = db.getSiblingDB(appDatabase); try { appDb.createUser({ user: appUser, pwd: appPassword, roles: [{ role: "readWrite", db: appDatabase }], }); } catch (error) { if (!String(error).includes("already exists")) { throw error; } } ' "${DOCKER_CMD[@]}" stop invario-mongo-recovery >/dev/null trap - EXIT echo "MongoDB bootstrap abgeschlossen. Starte gesicherten Dienst erneut..." } if ! mongo_bootstrap_needed; then bootstrap_mongo_users fi "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" up -d mongodb "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" up -d --no-deps website # Wait for website to become healthy (simple HTTP check) check_url="http://localhost:4999" timeout_seconds=60 interval=2 elapsed=0 echo "Warte auf Website (${check_url}) bis ${timeout_seconds}s..." while [ $elapsed -lt $timeout_seconds ]; do if curl -sS --max-time 2 "$check_url" >/dev/null 2>&1; then echo "Website erreichbar nach ${elapsed}s" break fi sleep $interval elapsed=$((elapsed + interval)) done if [ $elapsed -ge $timeout_seconds ]; then echo "[FEHLER] Website nicht erreichbar nach ${timeout_seconds}s. Sammle Diagnosedaten..." echo "--- docker compose ps ---" "${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" ps || true echo "--- docker logs website (tail 200) ---" "${DOCKER_CMD[@]}" logs --tail 200 website-website-1 || true echo "Bitte prüfe Container-Logs und nginx-Konfiguration." fi echo "Website stack is running on http://localhost:4999" echo "Provisioning creates self-signed certs per subdomain when needed."