Production correct-credential login returned auth_unavailable 503 because Flask's SECRET_KEY was unset: wrong-password probes stopped at 401 before CSRF token issuance, while valid credentials reached _csrf_serializer() and crashed. App factory now rejects absent/short (<32 char) SECRET_KEY at startup, and docker_entrypoint.sh fails fast before migration/services. Bootstrap no longer passes ADMIN_PASSWORD in process arguments; env-only. Tests: app-factory + entrypoint regression (5 focused passed), full backend suite 204 passed. Independent review PASS.
59 lines
2.3 KiB
Bash
59 lines
2.3 KiB
Bash
#!/usr/bin/env bash
|
|
# Docker entrypoint for CrowdSight production image.
|
|
#
|
|
# Runs database migrations to head BEFORE starting any service, so that the
|
|
# backend (gunicorn) and the durable worker never query tables that do not
|
|
# exist yet (fixes worker crash-loop: "no such table: jobs").
|
|
#
|
|
# - Require DATABASE_URL to be set (fail fast with a clear message).
|
|
# - Run `alembic upgrade head` (idempotent; no-ops when already at head).
|
|
# - Then exec supervisord to run nginx + backend + worker.
|
|
|
|
set -euo pipefail
|
|
|
|
cd /app/backend
|
|
|
|
if [[ -z "${DATABASE_URL:-}" ]]; then
|
|
echo "[entrypoint] FATAL: DATABASE_URL is not set. Refusing to start." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ -z "${SECRET_KEY:-}" ]]; then
|
|
echo "[entrypoint] FATAL: SECRET_KEY is not set. Authentication sessions and CSRF tokens cannot be signed." >&2
|
|
exit 1
|
|
fi
|
|
|
|
if [[ ${#SECRET_KEY} -lt 32 ]]; then
|
|
echo "[entrypoint] FATAL: SECRET_KEY must be at least 32 characters." >&2
|
|
exit 1
|
|
fi
|
|
|
|
# If DATABASE_URL points at Postgres, fail fast with a clear message if the
|
|
# psycopg driver is missing (instead of a confusing SQLAlchemy
|
|
# NoSuchModuleError inside alembic).
|
|
if [[ "$DATABASE_URL" == postgres* ]]; then
|
|
if ! uv run --frozen python -c "import psycopg" 2>/dev/null; then
|
|
echo "[entrypoint] FATAL: DATABASE_URL is PostgreSQL but the psycopg driver is not installed in this image. Rebuild the image so 'uv sync' installs psycopg[binary]." >&2
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "[entrypoint] Running database migrations (alembic upgrade head)..."
|
|
uv run --frozen alembic upgrade head
|
|
echo "[entrypoint] Migrations complete."
|
|
|
|
# Idempotent first-admin bootstrap. Only runs when ADMIN_EMAIL and
|
|
# ADMIN_PASSWORD are provided; it creates/updates a super_admin user and org
|
|
# (never overwrites an existing password). Optional in the image so a deployed
|
|
# container can self-provision its first super_admin on startup.
|
|
if [[ -n "${ADMIN_EMAIL:-}" && -n "${ADMIN_PASSWORD:-}" ]]; then
|
|
echo "[entrypoint] Bootstrapping first super_admin (${ADMIN_EMAIL})..."
|
|
uv run --frozen python scripts/bootstrap_super_admin.py
|
|
echo "[entrypoint] super_admin bootstrap complete."
|
|
else
|
|
echo "[entrypoint] ADMIN_EMAIL/ADMIN_PASSWORD not set; skipping auto bootstrap."
|
|
fi
|
|
|
|
echo "[entrypoint] Starting supervisord (nginx + backend + worker)..."
|
|
exec /usr/bin/supervisord -n
|