#!/usr/bin/env bash set -euo pipefail export POSTGRES_DB="${GEOINTEL_POSTGRES_DB:-${POSTGRES_DB:-geointel}}" export POSTGRES_USER="${GEOINTEL_POSTGRES_USER:-${POSTGRES_USER:-geointel}}" export POSTGRES_PASSWORD="${GEOINTEL_POSTGRES_PASSWORD:-${POSTGRES_PASSWORD:-geointel}}" export PGDATA="${PGDATA:-/var/lib/postgresql/data}" export STORAGE_ROOT="${STORAGE_ROOT:-${GEOINTEL_STORAGE_ROOT:-/app/storage}}" export DATABASE_URL="${DATABASE_URL:-postgresql+psycopg://${POSTGRES_USER}:${POSTGRES_PASSWORD}@127.0.0.1:5432/${POSTGRES_DB}}" export CORS_ORIGINS="${GEOINTEL_CORS_ORIGINS:-${CORS_ORIGINS:-http://localhost:1202,http://127.0.0.1:1202}}" export MAX_UPLOAD_MB="${GEOINTEL_MAX_UPLOAD_MB:-${MAX_UPLOAD_MB:-500}}" export YOLO_MODELS_DIR="${YOLO_MODELS_DIR:-/app/models}" export YOLO_CONFIG_DIR="${YOLO_CONFIG_DIR:-$STORAGE_ROOT/ultralytics}" export GEOINTEL_RECONCILE_INTERRUPTED_RUNS_ON_STARTUP="${GEOINTEL_RECONCILE_INTERRUPTED_RUNS_ON_STARTUP:-true}" case "$MAX_UPLOAD_MB" in ''|*[!0-9]*) echo "GEOINTEL_MAX_UPLOAD_MB must be a whole number between 1 and 2048." >&2 exit 2 ;; esac if [ "$MAX_UPLOAD_MB" -lt 1 ] || [ "$MAX_UPLOAD_MB" -gt 2048 ]; then echo "GEOINTEL_MAX_UPLOAD_MB must be between 1 and 2048." >&2 exit 2 fi case "${GEOINTEL_ENV:-production}:${POSTGRES_PASSWORD}" in production:|production:geointel|production:postgres|production:password|production:changeme|production:change-me-before-shared-use) echo "Refusing to start production with an empty or known-default PostGIS password." >&2 exit 2 ;; esac sed -i "s/__GEOINTEL_MAX_UPLOAD_MB__/${MAX_UPLOAD_MB}/g" /etc/nginx/conf.d/default.conf nginx -t mkdir -p "$PGDATA" "$STORAGE_ROOT" "$YOLO_CONFIG_DIR" /run/nginx /var/log/nginx chown -R postgres:postgres "$PGDATA" postgres_pid="" backend_pid="" shutdown() { if [ -n "$backend_pid" ] && kill -0 "$backend_pid" 2>/dev/null; then kill "$backend_pid" 2>/dev/null || true fi if [ -n "$postgres_pid" ] && kill -0 "$postgres_pid" 2>/dev/null; then kill "$postgres_pid" 2>/dev/null || true wait "$postgres_pid" 2>/dev/null || true fi } trap shutdown INT TERM EXIT echo "Starting embedded PostGIS..." /usr/local/bin/docker-entrypoint.sh postgres & postgres_pid="$!" echo "Waiting for embedded PostGIS..." for attempt in $(seq 1 60); do if pg_isready -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then echo "PostGIS is ready after attempt ${attempt}." break fi if ! kill -0 "$postgres_pid" 2>/dev/null; then echo "PostGIS process exited before becoming ready." wait "$postgres_pid" fi sleep 2 done if ! pg_isready -h 127.0.0.1 -U "$POSTGRES_USER" -d "$POSTGRES_DB" >/dev/null 2>&1; then echo "PostGIS did not become ready." exit 1 fi echo "Applying Alembic migrations..." python -m alembic upgrade head echo "Starting GeoIntel backend..." uvicorn app.main:app --host 127.0.0.1 --port 8000 & backend_pid="$!" echo "Waiting for GeoIntel backend..." python - <<'PY' import time import urllib.request last_error = None for attempt in range(1, 61): try: urllib.request.urlopen("http://127.0.0.1:8000/health/ready", timeout=3).read() print(f"Backend is ready after attempt {attempt}.") break except Exception as exc: last_error = exc print(f"Backend not ready yet ({attempt}/60): {exc}") time.sleep(1) else: raise SystemExit(f"Backend did not become ready: {last_error}") PY echo "Starting nginx frontend on container port 80..." exec nginx -g "daemon off;"