Files
Key-service-Server/Website/launch.sh
T

185 lines
5.7 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"
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" <<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
}
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
}
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."