This page documents apps/api/.env.example, the SaaS distribution template
(EDITION=saas). Validated by apps/api/src/config/env.ts — the API fails closed at boot in
production if a required secret is missing. Enterprise self-hosted and enterprise_hybrid
deployments use the same variable names but different infrastructure values; see
Installation.
Never commit real values for anything marked Secret below. Production secrets should live
in Cloudflare Worker secrets, your container platform’s secret store, or an equivalent
customer-managed vault for enterprise self-hosted deployments.
Edition and runtime
| Variable | Secret | Notes |
|---|
EDITION | | saas for this template. Self-hosted uses self_hosted / enterprise_hybrid. |
NODE_ENV | | production enables strict, fail-closed validation of every production secret. |
PORT | | HTTP port for the Node/Docker runtime. |
Core infrastructure
System metadata and tenant data live in two physically separate Postgres databases — see
Tenants & Data Boundaries. Each has an owner/admin URL (for
migrations) and a restricted app-role URL (for runtime queries).
| Variable | Secret | Notes |
|---|
PLATFORM_DATABASE_URL | Yes | Owner connection for system-metadata migrations. |
PLATFORM_APP_DATABASE_URL | Yes | Restricted runtime connection for system metadata. |
TENANT_DATABASE_URL | Yes | Owner connection for tenant-plane migrations. |
TENANT_APP_DATABASE_URL | Yes | Restricted runtime connection for the tenant plane; RLS-scoped by app.tenant_id. |
REDIS_URL | Yes | Sessions, rate limits, nonces. Blank falls back to in-memory (single process only — no real session revoke). |
Auth
| Variable | Secret | Notes |
|---|
JWT_ACCESS_SECRET | Yes | Signs short-lived access tokens. |
JWT_REFRESH_SECRET | Yes | Signs refresh tokens. |
JWT_ISSUER | | Default alforse-api. |
JWT_AUDIENCE | | Default alforse-clients. |
JWT_ACCESS_TTL | | Default 15m. |
JWT_REFRESH_TTL | | Default 30d. |
API_HMAC_SECRET | Yes | HMAC for signed, non-browser API requests; required in production. |
Public URLs and CORS
| Variable | Secret | Production value |
|---|
API_PUBLIC_URL | | https://api.alforse.com/api/v1 |
WEB_PUBLIC_URL | | https://deals.alforse.com |
DEALS_PUBLIC_URL | | https://deals.alforse.com |
CONSOLE_PUBLIC_URL | | https://console.alforse.com |
CORS_ALLOWED_ORIGINS | | Comma-separated list of the origins above. |
PUBLIC_REGISTRATION_ENABLED | | Must be false in production unless your deployment explicitly supports public trial signup. Most production tenants use redemption codes or assisted onboarding. |
Object storage (S3-compatible / Cloudflare R2)
| Variable | Secret | Notes |
|---|
OSS_ENDPOINT | | S3-compatible endpoint. Alforse Cloud uses Cloudflare R2; enterprise self-hosted deployments use the approved customer-managed endpoint. |
OSS_BUCKET | | |
OSS_ACCESS_KEY | Yes | |
OSS_SECRET_KEY | Yes | |
OSS_REGION | | auto in production (R2). |
OCR
| Variable | Secret | Notes |
|---|
OCR_ENABLED | | Production: true. |
OCR_PROVIDER | | Production: mistral. |
OCR_ENDPOINT | | Production: https://document-ai.alforse.com/extract (the apps/document-ai Worker). |
OCR_API_KEY | Yes | |
OCR_ALLOW_UNAUTHENTICATED | | Keep false for any customer-facing deployment. |
OCR_TIMEOUT_MS | | Default 60000. |
License signing (self-hosted license issuance)
| Variable | Secret | Notes |
|---|
LICENSE_PRIVATE_KEY | Yes | Ed25519 private key (PEM). Required when your deployment issues signed self-hosted licenses. |
File scanning and download gating
| Variable | Secret | Notes |
|---|
FILE_SCAN_MODE | | external routes uploaded files to a scanning service before they’re downloadable; this is the strict/safe default and the only supported mode for a real deployment. |
FILE_SCAN_ENDPOINT | | |
FILE_SCAN_API_KEY | Yes | |
FILE_SCAN_TEMPORARY_BYPASS_ACK | | Explicit acknowledgment flag for the temporary bypass. |
FILE_SCAN_ALLOW_SKIPPED | | |
FILE_DOWNLOAD_REQUIRES_CLEAN_SCAN | | Strict/safe default is true. |
MFA
| Variable | Secret | Notes |
|---|
MFA_REQUIRED_FOR_ADMINS | | Production: true — admins must enroll TOTP MFA on first login. |
MFA_SECRET_KEY | Yes | Encrypts stored TOTP secrets; must be 32+ characters in production. |
Turnstile (human verification)
| Variable | Secret | Notes |
|---|
TURNSTILE_ENABLED | | Production: true. |
TURNSTILE_SECRET_KEY | Yes | Must match the frontend site key. |
TURNSTILE_ALLOWED_HOSTNAMES | | Production: deals.alforse.com,console.alforse.com. |
Turnstile applies to public auth endpoints (register, redeem, login, password reset, invite
accept). If you’re calling those endpoints directly instead of through the Deals/Console UI,
see Authentication for how turnstileToken fits into each
request.
Data handling / AI gateway
| Variable | Secret | Notes |
|---|
EXTERNAL_DATA_MODE | | Default redacted. |
AI_GATEWAY_MODE | | Default inspect. |
AI_GATEWAY_ALLOWED_PROVIDERS | | Allowed provider identifiers for AI inspection flows. |
AI_GATEWAY_ALLOWED_MODELS | | Allowed model identifiers for AI inspection flows. |
SSO (optional)
Configure providers in complete pairs — a half-configured pair is rejected in production, and a
missing pair simply hides that provider from GET /auth/sso/providers.
| Provider | Variables |
|---|
| Google | GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET |
| LinkedIn | LINKEDIN_CLIENT_ID, LINKEDIN_CLIENT_SECRET |
| Slack | SLACK_CLIENT_ID, SLACK_CLIENT_SECRET |
| DingTalk | DINGTALK_APP_KEY, DINGTALK_APP_SECRET |
| Lark | LARK_APP_ID, LARK_APP_SECRET |
All *_SECRET / *_APP_SECRET values are secrets.
Email
Transactional mail (password reset, invitations, MFA backup codes) defaults to the Resend HTTP
API — the only transport that’s safe from the Worker runtime, which cannot open raw TCP
sockets.
| Variable | Secret | Notes |
|---|
EMAIL_PROVIDER | | resend for SaaS. smtp is self-hosted only. |
RESEND_API_KEY | Yes | |
EMAIL_FROM | | Default "Alforse <[email protected]>". |
SMTP_HOST / SMTP_PORT / SMTP_SECURE / SMTP_STARTTLS / SMTP_USER / SMTP_PASS / SMTP_FROM | SMTP_PASS is a secret | Self-hosted fallback only. With Resend’s SMTP bridge: host smtp.resend.com, user resend, password = your Resend API key. |