Skip to Content

Deployment

The backend ships as a Docker image whose entrypoint is start.sh, serving on port 8080. The same codebase runs in three roles: the API service, a migration job, and Celery workers.

Container

Build from the repository root:

build-image.sh
docker build -t rhesis-backend:latest -f apps/backend/Dockerfile .

Run it with an env file (see Environment configuration for the variables it expects):

run-container.sh
docker run -p 8080:8080 --env-file ./apps/backend/.env.docker rhesis-backend:latest

start.sh loads .env in local mode, applies migrations via migrate.sh when a database is configured, then starts the server (Gunicorn with Uvicorn workers in production, Uvicorn otherwise).

Migrations

By default the API applies migrations on boot: start.sh calls migrate.sh, which runs alembic upgrade head. Setting SKIP_MIGRATIONS=true on the service suppresses that, for deployments that apply schema changes as a separate step. The Helm chart does this: templates/backend/migrate-job.yaml runs migrate.sh as a pre-sync Job and sets SKIP_MIGRATIONS=true on the backend pods (backend.migrations.job.enabled).

Make migrations backward compatible so a new revision can run before the new code is fully rolled out. To roll a schema change back:

rollback-migration.sh
alembic downgrade -1

Workers

Celery workers deploy as their own service from the worker image, sharing the broker and result backend (BROKER_URL, CELERY_RESULT_BACKEND). Scale workers independently of the API. See Background tasks.

Kubernetes

The production target is Kubernetes. .github/workflows/backend-k8s.yml builds the image, pushes it to Artifact Registry, and syncs ArgoCD; the Helm chart lives in charts/rhesis. Environment comes from the chart’s ConfigMap and existingSecret.

The image is a standard container, so it also runs on other platforms (AWS ECS, Azure Container Apps, plain Docker) given the same environment variables.

Operations

  • HealthGET /health returns {"status": "ok"}; use it as the container health check.
  • Logs — the application logs to stdout/stderr; set JSON_LOGGER_ENABLED=true for structured logs (see Architecture).
  • Rollback — redeploy the previous image; reverse migrations only if the new revision was not backward compatible.
  • Secrets — supply JWT_SECRET_KEY, database, and OAuth credentials through the platform’s secret manager, not the image.