Skip to content
EvalBook

Deployment

Coolify builds the repository's Dockerfile from main and runs one container with the API, the worker and the web app; the environment it needs, what must be registered at SSO first, and the production addresses.

EvalBook deploys the way its sibling products do: Coolify watches the repository's main branch and auto-deploys every push, building the repository's own Dockerfile. Nixpacks is not used. The result is one container running three processes, backed by one PostgreSQL database. There are no GitHub Actions.

The production origin was decided on 25 October 2026: the application is https://app.nurobook.com (www.app.nurobook.com also points there) and this site is https://nurobook.com. Nothing in the application hard-codes a domain: SSO's seed registers EvalBook only when EVALBOOK_APP_ORIGIN is set in SSO's environment, and EvalBook learns its own addresses from EVALBOOK_APP_URL and from SSO. The product keeps its name, EvalBook.

What the container runs

The image is node:24-bookworm-slim with the web app built in at image build time, so a restart never waits on a build. scripts/coolify-start.sh is the entrypoint:

  1. Builds the database connection from EVALBOOK_DB_* and exports it; no file with a password is written. A missing variable stops the start, naming it.
  2. Creates any missing tables (scripts/bootstrap.mjs coolify), then applies pending migrations (scripts/migrate-all.sh coolify).
  3. Starts the API on 127.0.0.1:8080 (internal; EVALBOOK_API_PORT overrides) and waits up to 60 seconds for /health.
  4. Starts the worker. The API runs no jobs in the container.
  5. Starts the web app with next start on $PORT (3000) on all interfaces. Next rewrites /api/* to the API on localhost, so the session cookie is first-party and nothing outside the container needs to know the API is a separate process.

If any of the three processes exits, the container exits and Coolify restarts it: a dead worker behind a live /health would otherwise hide. The image's health check probes the web port every 30 seconds after a 90-second start period. What /health and /ready answer is on Readiness and operations.

Environment variables in production

Set these in Coolify. Never print or commit a value.

Variable Purpose
SSO_ORIGIN the Bookbag SSO API origin
SSO_APP_TOKEN EvalBook's app token from SSO's app registry
SSO_UI_ORIGIN only if the SSO UI is on a different origin from its API
EVALBOOK_ENCRYPTION_KEY 32 bytes as 64 hex characters or base64; readiness fails without it
EVALBOOK_APP_URL the web origin, used in links EvalBook writes
EVALBOOK_ALLOWED_ORIGINS CORS origins beyond the app's own, comma-separated, if any
EVALBOOK_DB_HOST, EVALBOOK_DB_PORT, EVALBOOK_DB_NAME, EVALBOOK_DB_USER, EVALBOOK_DB_PASSWORD the PostgreSQL database; every context shares it
EVALBOOK_DB_SSL=1 (and EVALBOOK_DB_SSL_INSECURE=1 only for a self-signed certificate) TLS to the database
EVALBOOK_DIAGNOSTICS_TOKEN optional; lets a monitor read the /ready detail with a Bearer header; at least 32 characters
NEXT_PUBLIC_SSO_ORIGIN the SSO UI origin the web app sends people to for sign-in, sign-out and account links

master=coolify, NODE_ENV=production and PORT=3000 are set in the image. PEER_SECRET and the PEER_*_URL overrides are for local work only; production sets none and reads the peer directory from SSO.

Register EvalBook at SSO first

The container cannot serve a sign-in until SSO knows it. At SSO:

  1. Set EVALBOOK_APP_ORIGIN in SSO's environment to the web origin. SSO's seed then registers EvalBook (bookbag-evalbook) with the peer prefix /project/api/peer; the redirect URI is <web origin>/api/auth/sso/callback.
  2. Add the same origin to SSO_ALLOWED_ORIGINS and to SSO_CHAT_ORIGINS.
  3. Issue the app token from SSO's app registry and set it as SSO_APP_TOKEN here. It is shown once.
  4. Give the people who will run EvalBook the per-product admin role for EvalBook at SSO; that is what makes them platform admins here. See Platform admin.

CodeBook, MadeBook and EvalBook find each other through SSO's peer directory; nothing about peers is configured in Coolify. See Peer links.

The runner is not in the container

Executable scorers never run in this container. The API and worker execute no customer code; the runner is a single file installed separately on the customer's machine, dials out to EvalBook with a runner token (evr_…) and opens no port. Deploying EvalBook deploys no runner. See Executable verification.

Verifying a deployment

After Coolify reports the container healthy:

  • GET /health answers 200 with status: "ok".
  • GET /ready answers 200; with the diagnostics token, every check is pass.
  • Sign in through SSO and open Admin → Readiness as a platform admin; the same checks appear with their detail.
  • Open an organization and create a project; the free plan allows 3 active projects per organization, and EvalBook is not yet billable at SSO, so every organization is on the free plan.

The topology decision calls for daily database backups, as the siblings have; backup and restore rehearsal is not yet recorded in the requirements ledger. Service-level targets are proposals until load tests run on this topology and are not advertised.