RAMSIO

Docs

Environment Variables

Every variable in the real .env.example — names and purpose only. No real keys, secrets, or values live on this page or anywhere in this site.

Node & Postgres (Docker Compose)

VariablePurpose
NODE_ENVdevelopment | production | test.
ENABLE_SWAGGER_IN_PRODSwagger UI at /api/docs is disabled by default once NODE_ENV=production (it’s reconnaissance value for an attacker, not something end users need). Set true to explicitly re-enable it.
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DBOnly used by docker-compose.yml to provision the local Postgres container — not read by the app itself once DATABASE_URL points at a real database.

Database

VariablePurpose
DATABASE_URLrequiredPostgreSQL connection string for Prisma.

JWT & session secrets

Symmetric secrets (openssl rand -base64 32), not keypairs. Access and refresh tokens are signed with separate secrets on purpose — a leaked refresh secret alone can’t forge access tokens.

VariablePurpose
JWT_SECRETrequiredSigns and verifies access tokens. Minimum 32 characters — the API refuses to start with a shorter one or a leftover placeholder value.
JWT_REFRESH_SECRETrequiredSigns and verifies refresh tokens. Same 32-character minimum.
JWT_ACCESS_EXPIRYAccess token lifetime. Default 15m.
JWT_REFRESH_EXPIRYRefresh token lifetime. Default 7d.
COOKIE_SECRETrequiredSigns the httpOnly refresh-token cookie.
ENCRYPTION_KEYrequiredAES key for field-level PII encryption at rest (emails, phone numbers).
AUDIT_LOG_HMAC_SECRETHMAC key for audit-log tamper-evidence (audit-logs module, ENTERPRISE tier). Falls back to JWT_SECRET if unset so logging never breaks — but that means a leaked JWT secret also compromises audit-log integrity, not just token forgery. Worth setting separately.
AUDIT_LOG_RETENTION_DAYSHow long audit log entries are kept before the purge scheduler deletes them. Defaults to 365 days.

Auth policy

All optional — sane defaults ship without setting any of these.

VariablePurpose
AUTH_MAX_LOGIN_ATTEMPTSFailed logins before account lockout. Default 5.
AUTH_LOCKOUT_MINUTESLockout duration once the attempt limit is hit. Default 15.
AUTH_EMAIL_VERIFICATION_EXPIRY_HOURSDefault 24.
AUTH_PASSWORD_RESET_EXPIRY_HOURSDefault 24.
AUTH_RECENT_AUTH_WINDOW_MINUTESHow recently a user must have actually logged in (not merely refreshed a token) before a step-up action — changing their password, deleting their account — is allowed. Default 15. Enforced by RecentAuthGuard.

API server & reverse proxy

VariablePurpose
PORTAPI listen port. 12002 in every shipped config.
TRUST_PROXY_ADDRESSESComma-separated trusted reverse-proxy IP(s)/CIDR range(s) (nginx-ingress, ALB, Cloudflare). Leave unset with no proxy in front. Only set this behind a proxy that provably strips/overwrites inbound X-Forwarded-For before appending its own hop — otherwise a client can forge that header to get a fresh, never-throttled rate-limit bucket on every request (a real, confirmed exploit path against /auth/login without this set correctly). Per-account brute-force lockout is unaffected either way, since that’s tracked by user row, not IP.

Frontend & CORS

VariablePurpose
NEXT_PUBLIC_API_URLrequiredAPI origin the browser calls directly. Inlined into the Next.js client bundle at BUILD time — must be a Docker build-arg, not a runtime env var, when building the web image.
FRONTEND_URLrequiredThe canonical web app origin — used by the API for CORS, email links, and OAuth/checkout redirect allowlisting.
CORS_ADDITIONAL_ORIGINSOptional comma-separated origins to allow via CORS beyond FRONTEND_URL (a staging environment, or an apex + www split). Only affects CORS — email links and redirects always use FRONTEND_URL.
API_URLThe API’s own public URL, read live at runtime by the API process itself — used to build absolute callback URLs it constructs server-side (currently: the SAML SSO ACS callback in the mfa module). Distinct from NEXT_PUBLIC_API_URL, which is inlined into the browser bundle. Required if SSO is enabled and a provider doesn’t set its own callback URL — left unset, the callback silently becomes the literal string "undefined/mfa/sso/acs" instead of failing loudly.

Valkey

VariablePurpose
REDIS_URLrequiredValkey (Redis-protocol-compatible) connection string — caching, queues, rate-limit buckets.

Email (Resend)

VariablePurpose
RESEND_API_KEYRequired for email features — verification, password reset, team invitations.
FROM_EMAILSender address for all transactional email.

Billing — Stripe

VariablePurpose
STRIPE_SECRET_KEYRequired for billing features.
STRIPE_PUBLISHABLE_KEYUsed server-side.
STRIPE_WEBHOOK_SECRETVerifies the Stripe webhook signature.
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYSame publishable key, set again for the web app — it’s a separate deployment target and can’t read apps/api’s .env. Safe to expose to the browser: this key can only create tokens/PaymentMethods, never charge anything on its own. Inlined into the client bundle at build time.

Billing — Razorpay (India)

VariablePurpose
RAZORPAY_KEY_IDRequired for the Indian payment gateway.
RAZORPAY_KEY_SECRETRazorpay API secret.
RAZORPAY_WEBHOOK_SECRETVerifies the Razorpay webhook signature (HMAC-SHA256).

OAuth providers (PRO tier)

VariablePurpose
GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_CALLBACK_URLGoogle OAuth app credentials and callback URL.
GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET / GITHUB_CALLBACK_URLGitHub OAuth app credentials and callback URL.
MICROSOFT_CLIENT_ID / MICROSOFT_CLIENT_SECRET / MICROSOFT_CALLBACK_URLMicrosoft OAuth app credentials and callback URL.

MFA (ENTERPRISE tier)

VariablePurpose
WEBAUTHN_RP_IDMust exactly match your public domain (no protocol, no port). Defaults to localhost — fine for local dev, wrong for anything else. A mismatch fails passkey registration and login without an obvious error.
WEBAUTHN_ORIGINMust exactly match the full origin users access the app from. Defaults to http://localhost:12003.
TWILIO_ACCOUNT_SID / TWILIO_AUTH_TOKEN / TWILIO_PHONE_NUMBERSMS-based MFA delivery via Twilio.

Webhooks & licensing

VariablePurpose
WEBHOOK_DELIVERY_RETENTION_DAYSHow long outbound webhook delivery logs are kept before a scheduled purge (data minimization). Default 90; 0 disables the purge.
LICENSE_SERVER_URL / LICENSE_SECRETLicense key validation, if your deployment uses one.

Observability

VariablePurpose
LOG_LEVELerror | warn | info | debug | verbose.
SENTRY_DSNBackend error tracking (optional).
NEXT_PUBLIC_SENTRY_DSNFrontend error tracking — public DSN, safe to expose to the browser.
SENTRY_ORG / SENTRY_PROJECT_API / SENTRY_PROJECT_WEBSource-map upload targets — set as CI variables, not local env.

Analytics & marketing (optional, frontend)

All NEXT_PUBLIC_ — exposed to the browser by design.

VariablePurpose
NEXT_PUBLIC_GA_MEASUREMENT_IDGoogle Analytics.
NEXT_PUBLIC_FACEBOOK_PIXEL_IDMeta Pixel.
NEXT_PUBLIC_GOOGLE_ADS_IDGoogle Ads conversion tracking.
NEXT_PUBLIC_LINKEDIN_PARTNER_IDLinkedIn Insight Tag.
Generate the four random secrets before your first deploy — the exact command is on the Deployment page. The API refuses to start if a critical secret is missing, still contains a placeholder string, or is under 32 characters.