Files
microfish/backend/docker_entrypoint.sh
Kunthawat Greethong 9b0c0da9cb deploy: auto-bootstrap first super_admin on startup (ADMIN_* env)
With this, a fresh deploy provisions its own first super_admin automatically:
after alembic migrations the entrypoint runs scripts/bootstrap_super_admin.py
when ADMIN_EMAIL + ADMIN_PASSWORD are set (idempotent, never overwrites an
existing password; org name/slug optional). This removes the chicken-egg where
login needs a user but no UI/seed could create the very first one.

Optionally runs only when both env vars are present, so an existing deployment
is unaffected. Verified: bash syntax ok; fresh DB produced org+password+
super_admin; re-run left the existing password unchanged.
2026-09-01 14:31:31 +07:00

51 lines
2.1 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 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 \
--email "${ADMIN_EMAIL}" --password "${ADMIN_PASSWORD}" \
--org "${ADMIN_ORG_NAME:-Acme}" --slug "${ADMIN_ORG_SLUG:-}"
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