171 lines
4.8 KiB
Bash
Executable File
171 lines
4.8 KiB
Bash
Executable File
#!/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"
|
|
|
|
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" <<EOF
|
|
MONGO_INITDB_ROOT_USERNAME=${MONGO_INITDB_ROOT_USERNAME:-website_root}
|
|
MONGO_INITDB_ROOT_PASSWORD=$MONGO_INITDB_ROOT_PASSWORD
|
|
MONGO_APP_USER=${MONGO_APP_USER:-website_app}
|
|
MONGO_APP_PASSWORD=$MONGO_APP_PASSWORD
|
|
EOF
|
|
chmod 600 "$SECRETS_FILE"
|
|
# shellcheck disable=SC1090
|
|
source "$SECRETS_FILE"
|
|
export MONGO_INITDB_ROOT_USERNAME MONGO_INITDB_ROOT_PASSWORD MONGO_APP_USER MONGO_APP_PASSWORD
|
|
}
|
|
|
|
ensure_mongo_app_user() {
|
|
"${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 '
|
|
const appDatabase = process.env.MONGO_DB_NAME || "Invario_Website";
|
|
const appUser = process.env.MONGO_APP_USER || "website_app";
|
|
const appPassword = process.env.MONGO_APP_PASSWORD;
|
|
|
|
if (!appPassword) {
|
|
throw new Error("Missing MONGO_APP_PASSWORD");
|
|
}
|
|
|
|
const appDb = db.getSiblingDB(appDatabase);
|
|
if (!appDb.getUser(appUser)) {
|
|
appDb.createUser({
|
|
user: appUser,
|
|
pwd: appPassword,
|
|
roles: [{ role: "readWrite", db: appDatabase }],
|
|
});
|
|
print("created app user");
|
|
} else {
|
|
appDb.updateUser(appUser, {
|
|
pwd: appPassword,
|
|
roles: [{ role: "readWrite", db: appDatabase }],
|
|
});
|
|
print("updated app user");
|
|
}
|
|
'
|
|
}
|
|
|
|
wait_for_mongo_ready() {
|
|
local timeout_seconds=60
|
|
local interval=2
|
|
local elapsed=0
|
|
|
|
while [ $elapsed -lt $timeout_seconds ]; do
|
|
if "${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').ok" >/dev/null 2>&1; then
|
|
return 0
|
|
fi
|
|
sleep $interval
|
|
elapsed=$((elapsed + interval))
|
|
done
|
|
|
|
echo "[FEHLER] MongoDB wurde nicht rechtzeitig erreichbar." >&2
|
|
return 1
|
|
}
|
|
|
|
resolve_docker_cmd() {
|
|
if docker info >/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
|
|
}
|
|
|
|
compose() {
|
|
"${DOCKER_CMD[@]}" compose --env-file "$SECRETS_FILE" "$@"
|
|
}
|
|
|
|
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
|
|
|
|
compose build website
|
|
compose up -d mongodb
|
|
wait_for_mongo_ready
|
|
ensure_mongo_app_user
|
|
compose 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 ---"
|
|
compose 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." |