Skip to content

Configuration

Configuration system

A configuration management system enables type checking and automatic value merging in the following priority order (highest wins):

txt
default variables → configuration file variables → environment variables

Environment variables are parsed to extract only keys with specific prefixes (improving security). Keys are split by __ (double underscore) to reconstruct the nested configuration object. Arrays must be passed as JSON strings.

PrefixNamespaceDescription
API__apiServer host, port, domain, version
DB__dbDatabase connection URL
AUTH__authBetterAuth secret, base URL, Redis
KEYCLOAK__keycloakKeycloak OIDC federation settings
ADMIN__adminInitial admin user credentials
MODULES__modulesFeature module toggles

Configuration files:

  • Development: apps/api/config-example.json
  • Production: /app/config.json (mounted at runtime)

API

The API is built on top of Fastify with the following plugins already configured:

The API is fully typed and validated through Zod schemas, with a custom type-safe routing system providing full type safety for request/response validation and automatic OpenAPI documentation generation.

Notes:

  • Swagger UI is available at http(s)://<api_domain>/swagger-ui. It exposes two spec sources: Application API (Fastify routes) and Auth API (BetterAuth — select from the top-right dropdown). A standalone Scalar reference UI for auth is also available at /api/v1/auth/reference.
  • A getApiClient function is exported from the shared package, providing a typed fetch client for other apps and packages that consume the API.

Database

Prisma is used as the ORM, providing type-safe database access and migration management. The schema is split across multiple files:

  • prisma/schema.prisma — generator and datasource configuration
  • prisma/auth.prisma — BetterAuth-managed models (user, session, account, org, member, invitation, apiKey, jwks)
  • prisma/audit.prisma — audit log model

The codebase is structured to allow migration to other ORMs (e.g. Drizzle, Mongoose) by replacing the prisma/ folder and updating the resources/**/queries.ts files.

Endpoints

MethodPathAuthDescription
GET/api/v1/healthzPublicStartup probe
GET/api/v1/readyzPublicReadiness probe (checks DB)
GET/api/v1/livezPublicLiveness probe
GET/api/v1/versionPublicCurrent API version
ANY/api/v1/auth/*Public / AuthBetterAuth catch-all
GET/api/v1/auth/referencePublicInteractive OpenAPI reference (Scalar UI)
GET/api/v1/projectsAuthenticatedList own projects (admin: all projects)
GET/api/v1/projects/:idAuthenticatedGet own project by ID (admin: any)
POST/api/v1/projectsAuthenticatedCreate project (owner = current user)
PUT/api/v1/projects/:idAuthenticatedUpdate own project (admin: any)
DELETE/api/v1/projects/:idAuthenticatedDelete own project (admin: any)

Ownership rules: regular users can only read, update, or delete projects they own (ownerId matches their session user ID). Admins bypass ownership checks. The ownerId is set automatically from the session on creation — it is not a caller-supplied field.

Environment variables

Auth & Keycloak

VariableDescriptionDefault / Example
AUTH__SECRET256-bit secret for session signing(required in production)
AUTH__BASE_URLPublic API base URLhttp://localhost:8081
AUTH__TRUSTED_ORIGINSComma-separated list of trusted CORS originshttp://localhost:3000
AUTH__REDIS_URLStandalone Redis URL for session secondary storageredis://redis:6379 (optional)
AUTH__REDIS_SENTINEL_URLSComma-separated host:port pairs for Sentinel mode — takes precedence over REDIS_URLredis:26379,redis-2:26379 (optional)
AUTH__REDIS_SENTINEL_MASTERSentinel master name (required with REDIS_SENTINEL_URLS)mymaster
AUTH__REDIS_PASSWORDRedis node password for both standalone and Sentinel modes(optional)
AUTH__REDIS_SENTINEL_PASSWORDSentinel node password — falls back to AUTH__REDIS_PASSWORD when not set(optional)
KEYCLOAK__ENABLEDEnable Keycloak OIDC federationfalse
KEYCLOAK__CLIENT_IDKeycloak client IDtemplate-monorepo-ts
KEYCLOAK__CLIENT_SECRETKeycloak client secret
KEYCLOAK__ISSUERKeycloak realm issuer URLhttp://keycloak:8080/realms/<realm>
KEYCLOAK__MAP_ROLESSync Keycloak realm roles → BetterAuth rolefalse
KEYCLOAK__MAP_GROUPSSync Keycloak groups → BetterAuth rolefalse
ADMIN__EMAILBootstrap admin emailadmin@example.com (optional)
ADMIN__PASSWORDBootstrap admin password(optional)

Observability

VariableDescriptionDefault
OTEL_SERVICE_NAMEService name reported in traces and metricsapi
OTEL_EXPORTER_OTLP_ENDPOINTOTel Collector OTLP endpointhttp://otel-collector:4318
OTEL_SDK_DISABLEDDisable the OTel SDK entirelyfalse

OTel is automatically disabled in test environments (NODE_ENV=test).