Configuration
Environment variables for self-hosted Tokamak deployments
All configuration is via environment variables. In the shipped Compose stack they live in a single tokamak-services/.env file that the services consume through their Compose configuration.
This page covers what you need for a production deployment. For every variable and its default, see Environment Variables.
Required
| Variable | Description |
|---|---|
DB_POSTGRESQL_WRITE_DSN | PostgreSQL connection string, e.g. postgres://tokamak:tokamak@api-db:5432/tokamak |
COMPOSE_PROFILES | Which service groups to start. Nothing runs if this is empty. |
Change before going to production
These ship with development defaults that are unsafe on a public deployment.
| Variable | Why |
|---|---|
TOKAMAK_AUTH_SERVICE_TOKEN | Authenticates core → auth calls. The default is a well-known development value. |
MODEL_PROVIDER_SECRET | Encrypts stored provider credentials. The default is a well-known development value. |
AUTHZ_DELEGATION_PRIVATE_KEY | Signs the gateway's delegation JWTs. If unset an ephemeral key is generated, which breaks across restarts and across replicas. |
AUTHZ_DELEGATION_KEY_ID | Key ID published in the delegation JWKS. |
APIKEY_SECRET | Encrypts stored API keys. |
TOKAMAK_AUTH_ENCRYPTION_SECRET | Encrypts credentials held by the auth service. |
JWT_SIGNING_SECRET | Session signing key on the auth service — minimum 32 characters. Do not set it on core; core refuses to start if it is present. |
SYSTEM_ADMIN_EMAIL | Comma-separated emails seeded as platform owners on startup. Without it nobody can administer a fresh deployment. |
Service wiring
| Variable | Default | Description |
|---|---|---|
TOKAMAK_CORE_URL | http://tokamak-core:8090 | Where gateway and auth reach core |
TOKAMAK_AUTH_URL | http://tokamak-auth:8092 | Where gateway and core reach auth |
TOKAMAK_DELEGATION_JWKS_URL | — | The gateway's JWKS endpoint, so core can verify delegation tokens |
TOKAMAK_CORE_DB_SCHEMA | llm_api | Schema owned by core |
TOKAMAK_AUTH_DB_SCHEMA | tokamak_auth | Schema owned by auth |
AUTO_MIGRATE | true | Run core migrations on startup. Auth always migrates. |
Authentication
| Variable | Default | Description |
|---|---|---|
JWT_ACCESS_TOKEN_TTL | 1h | Access token lifetime |
JWT_REFRESH_TOKEN_TTL | 168h | Refresh token lifetime (7 days) |
API_KEY_DEFAULT_TTL | 2160h | Default API key lifetime (90 days) |
API_KEY_MAX_TTL | 2160h | Maximum API key lifetime |
API_KEY_MAX_PER_USER | 100 | Maximum keys per user |
API_KEY_PREFIX | sk_live | Prefix on issued keys |
OIDC (optional)
Keycloak is not part of the Compose stack. To use an existing installation:
| Variable | Description |
|---|---|
KEYCLOAK_ENABLED | Set to true to enable OIDC validation |
KEYCLOAK_BASE_URL | Base URL of the Keycloak deployment |
KEYCLOAK_REALM | Realm name |
KEYCLOAK_CLIENT_ID | Client ID |
With Keycloak disabled, the deployment still accepts API keys and self-signed session tokens.
Ports and networking
| Variable | Default | Description |
|---|---|---|
HTTP_PORT | 8080 on gateway, 8090 on core, 8092 on auth, 8093 on billing | Per-service listener |
CORS_ALLOWED_ORIGINS | — | Allowed origins on the gateway (comma-separated) |
CORS_EXTRA_ORIGINS | — | Additional origins on core |
Expose backend traffic through the gateway. Core, auth and billing are private in the base Compose files; the billing development override publishes a local port. Frontends and selected infrastructure also publish host ports.
Media storage
| Variable | Default | Description |
|---|---|---|
MEDIA_STORAGE_BACKEND | s3 | s3 or local |
MEDIA_S3_ENDPOINT | https://s3.menlo.ai | S3-compatible endpoint |
MEDIA_S3_BUCKET | — | Bucket name |
MEDIA_S3_ACCESS_KEY_ID | — | Access key |
MEDIA_S3_SECRET_ACCESS_KEY | — | Secret key |
MEDIA_S3_REGION | us-west-2 | Region |
MEDIA_LOCAL_STORAGE_PATH | — | Filesystem path when the backend is local |
MEDIA_LOCAL_STORAGE_BASE_URL | — | Base URL for locally stored media |
MEDIA_MAX_BYTES | 52428800 | Maximum file size (50 MB) |
MEDIA_PUBLIC_URL | http://localhost:8080 | Public-facing URL for media |
MEDIA_RETENTION_DAYS | 30 | Days before media is deleted |
Request archives
Off by default. When enabled, request and response payloads are written to S3 for audit and replay.
| Variable | Default | Description |
|---|---|---|
ARCHIVE_ENABLED | false | Enable archiving |
ARCHIVE_S3_BUCKET | — | Bucket name |
ARCHIVE_S3_REGION | us-west-2 | Region |
ARCHIVE_RETENTION_DAYS | 365 | Retention window |
ARCHIVE_COMPRESSION | true | Compress payloads |
Invitation email delivery
Configure these on auth. Leaving the host unset disables email delivery; administrators can still copy invitation links. Partial or invalid SMTP configuration fails startup.
| Variable | Default | Purpose |
|---|---|---|
INVITATION_SMTP_HOST | unset | SMTP server; enables delivery when configured |
INVITATION_SMTP_PORT | 587 | STARTTLS-capable SMTP port, not implicit TLS/465 |
INVITATION_SMTP_FROM | unset | Sender address |
INVITATION_SMTP_USERNAME, INVITATION_SMTP_PASSWORD | unset | Set both when the relay requires authentication |
INVITATION_SMTP_REQUIRE_TLS | true | Require STARTTLS; SMTP authentication always requires TLS |
INVITATION_APP_URL | unset | Customer app origin for invitation links; HTTPS required except loopback |
Use a local email sink and disposable recipients for development. Confirm delivery status and acceptance before inviting customers. Retries reuse the invitation credential; delivery is not proof of membership. A crash after SMTP acceptance can produce duplicate mail without duplicate grants.
Billing and payment setup
Billing runs privately on port 8093, owns the tokamak_billing schema and runs its migrations on boot. Provider credentials alone do not activate charging for every organization.
| Variable | Service | Purpose |
|---|---|---|
TOKAMAK_BILLING_DB_DSN | billing | Required database connection; falls back to DB_POSTGRESQL_WRITE_DSN |
TOKAMAK_BILLING_DB_SCHEMA | billing | Owned schema; default tokamak_billing |
TOKAMAK_BILLING_MODE | core | DISABLED by default; SHADOW observes; AUTHORITY follows per-organization activation |
TOKAMAK_BILLING_STRIPE_SECRET_KEY | billing | Enables the deposit provider surface; keep server-side |
TOKAMAK_BILLING_STRIPE_WEBHOOK_SECRET | billing | Enables signature-verified Stripe webhook handling |
TOKAMAK_BILLING_STRIPE_PUBLISHABLE_KEY | billing | Enables in-page card confirmation; must match the deployment's test/live band |
TOKAMAK_BILLING_CARD_ENTRY | billing | elements or checkout; unset chooses from configured capabilities. Stripe Elements requires a publishable key; Airwallex uses per-intent client secrets |
TOKAMAK_BILLING_RECEIPT_MODE | billing | both (default), stripe, or tokamak |
TOKAMAK_BILLING_CHECKOUT_RETURN_BASE_URL | billing | Public gateway base for the hosted checkout callback |
TOKAMAK_BILLING_CHECKOUT_APP_RETURN_URL | billing | Customer app destination after the callback |
TOKAMAK_BILLING_OPS_TOKENS | billing | Server-held credentials for internal operations; never expose to browsers |
This is an onboarding summary, not the full activation procedure. Configure service trust, provider band, webhooks, redirects, fee policy and organization activation together. Read the repository's tokamak-services/docs/reference/billing.md, env.md and billing-activation-runbook.md before an enforced rollout.
Use payment test mode and local test services for development. Verify quote review, a completed test purchase, credit settlement, receipt access and pending-payment recovery before opening purchases to customers. See Credits and billing for the customer workflow.
Adding Airwallex as a second payment provider
Billing talks to payment providers through one port with one adapter per provider. Stripe and Airwallex can be configured side by side; every stored deposit, saved card, refund and dispute keeps routing to the provider recorded on it. New purchases using a saved card use that card's provider; other new purchases use the deployment's default provider, which must be named explicitly.
| Variable | Service | Purpose |
|---|---|---|
TOKAMAK_BILLING_DEFAULT_PAYMENT_PROVIDER | billing | stripe or airwallex. Required whenever any payment credential is set — a Stripe-only deployment must set stripe before upgrading, or billing refuses to boot |
TOKAMAK_BILLING_AIRWALLEX_CLIENT_ID / TOKAMAK_BILLING_AIRWALLEX_API_KEY | billing | The Airwallex API credential, set together. Registers the Airwallex adapter; does not change the default |
TOKAMAK_BILLING_AIRWALLEX_ENV | billing | demo or prod. Checked against the deployment band at boot: prod requires live, demo requires test |
TOKAMAK_BILLING_AIRWALLEX_WEBHOOK_SECRET | billing | Enables the signature-verified webhook route POST /v1/billing/webhooks/airwallex |
Point an Airwallex webhook subscription at https://<gateway>/v1/billing/webhooks/airwallex and subscribe to the payment_intent.*, payment_attempt.*, refund.*, payment_dispute.*, payment_consent.* and payment_method.* events. Registering the adapter changes nothing for customers until the default provider is switched, which is a separate, gated change. The full ordered procedure, the verification steps and what is deliberately left disabled are in the repository's tokamak-services/docs/rollouts/airwallex-setup-runbook.md.
Logging and observability
| Variable | Default | Description |
|---|---|---|
LOG_LEVEL | info | debug / info / warn / error |
LOG_FORMAT | console | console or json — use json in production |
ENVIRONMENT | development | development or production |
OTEL_ENABLED | false | Enable OTLP trace and metric export |
OTEL_EXPORTER_OTLP_ENDPOINT | — | Collector endpoint |
See Observability.
Features
| Variable | Default | Description |
|---|---|---|
ENABLE_SWAGGER | true | Serve the Swagger UI |
MODEL_SYNC_ENABLED | true | Periodically refresh provider model lists |