Every environment variable read by either repo. Use this as the canonical reference when filling in a new .env, debugging missing-config errors, or reviewing a PR that touches config.
Sources scanned:
Backend: src/shared/config/index.ts, src/app.ts, every process.env.* reference in src/, and .env.sentry.example.
Frontend: .env.development, .env.local, .env.production, .env.sentry.example, next.config.ts, all process.env.* references in src/.
[!warning] Many secrets in the checked-in .env.* files of the frontend are publicly visible (Alchemy key, WalletConnect ID, Google OAuth client ID, Sentry DSN). Rotate these immediately if the repo leaks. Anything not marked NEXT_PUBLIC_ is not exposed to the browser.
How env is loaded
Backend
src/shared/config/index.ts calls dotenv.config({ path: '.env.development' }) and then dotenv.config() (default .env). In Docker dev, docker-compose.dev.yml injects env_file: .env.local and in production env_file: .env. There is no fallback: if a required var is missing, the typed access (process.env.JWT_SECRET!) yields undefined and the service crashes on first use.
Frontend
Next.js auto-loads .env, .env.local, .env.development, .env.production in the standard precedence order. Only variables prefixed NEXT_PUBLIC_ are exposed to the browser bundle. The production Dockerfile hard-codes several NEXT_PUBLIC_* values via ENV directives at build time so they are baked into the static bundle (see Docker Setup#frontend-dockerfile).
Database
Name
Repo
Required
Default
Example
Purpose
MONGODB_URI
backend
✅
—
mongodb://mongodb:27017
Mongo connection string (no auth in dev)
DB_NAME
backend
✅
—
marketplace
Database name appended to the URI
In docker-compose.production.yml the Mongo service is mongodb and is reachable as mongodb://mongodb:27017 from the backend container.
Cache / Redis
Name
Repo
Required
Default
Example
Purpose
REDIS_URI
backend
✅
—
redis://redis:6379
Connection string used by services/redis
REDIS_PASSWORD
backend
prod only
—
super-secret
Substituted into the prod Redis command line (--requirepass)
In dev, Redis runs without a password. In production the compose entrypoint is redis-server --requirepass "$REDIS_PASSWORD" so include :password@ in REDIS_URI accordingly.
Auth / JWT
Name
Repo
Required
Default
Example
Purpose
JWT_SECRET
backend
✅
—
64 hex chars
HMAC key for access tokens
JWT_EXPIRES_IN
backend
✅
—
1h
Access token lifetime
REFRESH_TOKEN_EXPIRES_IN
backend
✅
—
30d
Refresh token lifetime
ADMIN_EMAIL
backend
optional
admin@marketplace.com
—
Email of the initial admin created by init-admin
ADMIN_PASSWORD
backend
optional
Moji6364
—
Password for the initial admin
ADMIN_FIRST_NAME
backend
optional
Admin
—
First name for the seeded admin
ADMIN_LAST_NAME
backend
optional
User
—
Last name for the seeded admin
GOOGLE_CLIENT_ID
backend
optional
—
...apps.googleusercontent.com
Verifies Google ID tokens server-side
[!warning] Rotate JWT_SECRET only during a maintenance window — every active session is invalidated.
Older alias for webhook secret; some payloads still use it
SHKEEPER_ALLOWED_TOKENS
backend
optional
USDT,USDC
USDT,USDC,BTC
Comma-separated list of accepted tokens
SHKEEPER_NETWORKS
backend
optional
bsc,polygon
bsc,polygon,eth
Networks enabled in checkout
SHKEEPER_ENVIRONMENT
backend
optional
production
sandbox
Switches SHKeeper sandbox vs prod behaviour
SHKEEPER_FORCE_PAYOUT_DEMO
backend
optional
false
true
Skips real-chain payout; demo-confirms after 5s
SHKEEPER_FORCE_REAL
backend
optional
false
true
Forces real-chain even in dev/sandbox
ADMIN_PAYOUT_WALLET_ADDRESS
backend
✅ for payouts
—
0xAc23…
Wallet that receives platform fees / payouts
ESCROW_WALLET_ADDRESS
backend
✅
—
0xa304…
Master escrow address used by payments service
RECEIVER_WALLET_ADDRESS
backend
optional
—
0x…
Used by alternative payout flows
Payments — Provider Selection
Name
Repo
Required
Default
Example
Purpose
PAYMENT_PROVIDER
backend
optional
shkeeper
request.network
Active provider for new payment intents
PAYMENT_DEFAULT_PROVIDER
backend
optional
shkeeper
shkeeper
Fallback alias when PAYMENT_PROVIDER is unset
PAYMENT_ENABLED_PROVIDERS
backend
optional
shkeeper
shkeeper,request.network
Comma-separated providers allowed at runtime
PAYMENT_ROLLBACK_PROVIDER
backend
optional
shkeeper
shkeeper
Provider used when selected provider is not enabled
PAYMENT_PROVIDER_MODE
backend
optional
live
dry-run
Provider mode: live, dry-run, or read-only
REQUEST_NETWORK_ENABLED
backend
optional
false
true
Adds request.network to enabled providers when no explicit list is set
PAYMENT_REQUEST_NETWORK_COHORT_PERCENT
backend
optional
0
10
Percent of new checkout cohort eligible for Request Network
REQUEST_NETWORK_ALLOW_TEST_WEBHOOKS
backend
optional
false
false
Allows x-request-network-test webhook bypass only in explicit test mode. Keep false in dev/prod unless running a controlled smoke test.
TRANSACTION_SAFETY_ENABLED
backend
optional
true
true
Enables the Transaction Safety Provider gate before Request Network pay-ins are marked completed.
TRANSACTION_SAFETY_REQUIRE_TX_HASH
backend
optional
true
true
Blocks completion when provider evidence does not include a transaction hash.
TRANSACTION_SAFETY_REQUIRE_TRANSFER_MATCH
backend
optional
true
true
Requires on-chain token/recipient/amount evidence to match the expected payment.
TRANSACTION_SAFETY_MIN_CONFIRMATIONS
backend
optional
12
12
Minimum chain confirmations required by the Transaction Safety Provider.
TRANSACTION_SAFETY_AML_PROVIDER
backend
optional
none
none
AML/sanctions provider adapter name. Non-none values should block until implemented/configured.
PAYMENT_LEDGER_ENFORCEMENT
backend
optional
false
true
Enforce ledger gates for release/refund
PAYMENT_RECONCILIATION_ENABLED
backend
optional
false
true
Enable scheduled provider reconciliation jobs
TREZOR_SAFEKEEPING_REQUIRED
backend
optional
false
true
Optional hardware-signature gate for release/refund confirmation. Only the literal value true enforces Trezor proof.
Payments — DePay / Web3 (frontend)
Name
Repo
Required
Default
Example
Purpose
NEXT_PUBLIC_DEPAY_INTEGRATION_ID
frontend
✅ for DePay
—
1330e2d3-…
DePay widget integration ID
NEXT_PUBLIC_ESCROW_WALLET_ADDRESS
frontend
✅
—
0xa304…
Escrow address shown to buyers in the wallet flow
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID
frontend
✅
—
283b54dd…
WalletConnect v2 project ID
NEXT_PUBLIC_ALCHEMY_API_KEY_MAINNET
frontend
✅
—
—
Alchemy RPC for mainnet
NEXT_PUBLIC_ALCHEMY_API_KEY_POLYGON
frontend
✅
—
—
Alchemy RPC for Polygon
NEXT_PUBLIC_ALCHEMY_API_KEY_SEPOLIA
frontend
optional
—
—
Alchemy RPC for Sepolia (testing)
OAuth
Name
Repo
Required
Default
Example
Purpose
GOOGLE_CLIENT_ID
backend
optional
—
…apps.googleusercontent.com
Verifies Google ID tokens server-side
NEXT_PUBLIC_GOOGLE_CLIENT_ID
frontend
✅ for Google login
—
…apps.googleusercontent.com
Client ID used by Google Identity Services in the browser
OpenAI
Name
Repo
Required
Default
Example
Purpose
OPENAI_API_KEY
backend
✅ for AI features
—
sk-…
Used by services/ai
OPENAI_DEFAULT_MODEL
backend
✅ for AI
gpt-4o-mini
gpt-4o
Default chat model
OPENAI_MODEL
backend
optional
falls back to default
gpt-4o
Per-call override read in legacy paths
OPENAI_MAX_TOKENS
backend
✅ for AI
1024
4096
Hard cap per request
OPENAI_TEMPERATURE
backend
✅ for AI
0.7
0.2
Decoded as float
App URLs
Name
Repo
Required
Default
Example
Purpose
FRONTEND_URL
backend
✅
—
http://localhost:8083
Used by CORS, Socket.IO origin, password-reset email links
BACKEND_URL
backend
optional
derived from PORT
http://localhost:5001
Used in webhook callbacks & emails
API_URL
backend
optional
${BACKEND_URL}/api
http://localhost:5001/api
Self-reference for outbound webhooks
PORT
backend
✅
—
5001
HTTP listen port
TRUST_PROXY
backend
optional
auto-on in prod
true
Enables app.set('trust proxy', 1) for Nginx
NEXT_PUBLIC_APP_URL
frontend
✅
—
http://localhost:8083
Self-URL used in metadata + OG tags
NEXT_PUBLIC_APP_NAME
frontend
optional
AMN
ایسکرو آنلاین
Display name in nav / titles
NEXT_PUBLIC_APP_VERSION
frontend
optional
package.json
1.0.2
Shown in the version logger
NEXT_PUBLIC_API_URL
frontend
✅
—
http://localhost:5001/api
Axios base URL
NEXT_PUBLIC_API_BASE_URL
frontend
optional
derived
http://localhost:5001
Used by a few legacy callers
NEXT_PUBLIC_BACKEND_URL
frontend
✅
—
http://localhost:5001
Used by file URL builders
NEXT_PUBLIC_SERVER_URL
frontend
optional
mirror of backend URL
http://localhost:5001
Server-side rendering fallback
NEXT_PUBLIC_SOCKET_URL
frontend
✅
—
http://localhost:5001
Socket.IO endpoint
NEXT_PUBLIC_ASSETS_DIR
frontend
optional
""
/assets
Prefix for static asset URLs
NEXT_PUBLIC_MAPBOX_API_KEY
frontend
optional
—
pk.…
Mapbox token for delivery map
Rate limiting / files
Name
Repo
Required
Default
Example
Purpose
RATE_LIMIT_WINDOW_MS
backend
✅
—
900000
Express-rate-limit window
RATE_LIMIT_MAX_REQUESTS
backend
✅
—
100
Requests allowed per window per IP
MAX_FILE_SIZE
backend
✅
—
10485760 (10 MB)
Multer upload cap (bytes)
UPLOAD_PATH
backend
optional
/app/uploads
/var/uploads
Disk path for uploads (mounted volume)
Feature flags / seeding
Name
Repo
Required
Default
Example
Purpose
AUTO_SEED_ON_START
backend
optional
false
true
Re-seeds users/addresses/templates on boot if users is empty
SEED_USERS
backend
optional
false
true
One-shot user seeding flag honoured by seedUsers.ts
FORCE_SEED_TEMPLATES
backend
optional
false
true
Re-creates request templates even if some exist
BUILD_STATIC_EXPORT
frontend
optional
false
true
Static export build (currently unused)
NEXT_PUBLIC_IS_DEVELOPMENT
frontend
optional
false
true
Shows the dev-only banner & debug helpers
NEXT_PUBLIC_ENABLE_DEBUG
frontend
optional
false
true
Verbose console logging in the browser
NEXT_TELEMETRY_DISABLED
frontend
optional
0
1
Disables Next.js telemetry
Passkey / WebAuthn (frontend)
Name
Repo
Required
Default
Example
Purpose
NEXT_PUBLIC_PASSKEY_RP_NAME
frontend
optional
Amn
Amn
Relying-party display name
NEXT_PUBLIC_PASSKEY_RP_ID
frontend
optional
localhost
amn.gg
Relying-party origin host
NEXT_PUBLIC_PASSKEY_ORIGIN
frontend
optional
derived
https://amn.gg
Allowed origin for the WebAuthn challenge
Sentry
Name
Repo
Required
Default
Example
Purpose
NEXT_PUBLIC_SENTRY_DSN
frontend
optional
—
https://…ingest.sentry.io/…
Browser & server Sentry DSN
SENTRY_ORG
frontend
build-time
—
manawenuz
Used by @sentry/nextjs source-map upload
SENTRY_PROJECT
frontend
build-time
—
escrow-frontend
Sentry project slug
SENTRY_AUTH_TOKEN
frontend
build-time
—
—
Auth token for source-map upload (CI secret)
SENTRY_SUPPRESS_INSTRUMENTATION_FILE_WARNING
frontend
optional
—
1
Silences known dev warning
SENTRY_SUPPRESS_GLOBAL_ERROR_HANDLER_FILE_WARNING
frontend
optional
—
1
Silences known dev warning
SENTRY_DSN
backend
optional
—
https://…ingest.sentry.io/…
Backend Sentry DSN (set in src/config/sentry.ts)
The backend Sentry init runs before any other import (src/app.ts line 1) so DSN must be present in the env at process start.
Quick .env.local template (backend, dev)
NODE_ENV=development
PORT=5001TRUST_PROXY=false# DatabaseMONGODB_URI=mongodb://mongodb:27017
DB_NAME=marketplace
# CacheREDIS_URI=redis://redis:6379
# AuthJWT_SECRET=<openssl rand -hex 32>
JWT_EXPIRES_IN=1h
REFRESH_TOKEN_EXPIRES_IN=30d
# URLsFRONTEND_URL=http://localhost:8083
BACKEND_URL=http://localhost:5001
# Rate limitRATE_LIMIT_WINDOW_MS=900000RATE_LIMIT_MAX_REQUESTS=100# FilesMAX_FILE_SIZE=10485760UPLOAD_PATH=/app/uploads
# SMTPSMTP_HOST=smtp.example.com
SMTP_PORT=465SMTP_SECURE=trueSMTP_USER=SMTP_PASS=SMTP_FROM="AMN <no-reply@amn.gg>"# SHKeeper (set when ready)PAYMENT_PROVIDER=shkeeper
PAYMENT_ENABLED_PROVIDERS=shkeeper
PAYMENT_ROLLBACK_PROVIDER=shkeeper
REQUEST_NETWORK_ENABLED=falsePAYMENT_LEDGER_ENFORCEMENT=falsePAYMENT_RECONCILIATION_ENABLED=falseTREZOR_SAFEKEEPING_REQUIRED=falseSHKEEPER_BASE_URL=SHKEEPER_API_URL=SHKEEPER_API_KEY=SHKEEPER_WEBHOOK_SECRET=SHKEEPER_CALLBACK_SECRET=SHKEEPER_FORCE_PAYOUT_DEMO=true# OpenAI (optional)OPENAI_API_KEY=OPENAI_DEFAULT_MODEL=gpt-4o-mini
OPENAI_MAX_TOKENS=1024OPENAI_TEMPERATURE=0.7
# SeedingAUTO_SEED_ON_START=true# WalletsESCROW_WALLET_ADDRESS=0xa3049825c0785095EEd5E7976E0E539466c84044
ADMIN_PAYOUT_WALLET_ADDRESS=# Derived destinations (per-(buyer, sellerOffer) RN ephemeral wallets — Task #7)# Backend ONLY needs the xpub. The master seed must live in KMS/Trezor.DERIVED_DESTINATION_XPUB=# Only set DERIVED_DESTINATION_XPRIV when DERIVED_DESTINATION_SWEEP_SIGNER=hot-key# (dev shortcut). For prod, leave this blank and use the Trezor flow (Task #11).DERIVED_DESTINATION_XPRIV=DERIVED_DESTINATION_BASE_PATH=m/44'/60'/0'DERIVED_DESTINATION_CHAIN_ID=56DERIVED_DESTINATION_SWEEP_SIGNER=build-only
DERIVED_DESTINATION_MIN_SWEEP_AMOUNT=0DERIVED_DESTINATION_SWEEP_INTERVAL_MS=300000DERIVED_DESTINATION_SWEEP_AUTOSTART=true# OAuthGOOGLE_CLIENT_ID=
[!tip] Generate JWT_SECRET deterministically per environment so you don't accidentally invalidate sessions when restarting. Store it in your team's secret manager.
[!warning] DERIVED_DESTINATION_XPRIV is a development-only shortcut. In production, set DERIVED_DESTINATION_SWEEP_SIGNER=build-only and pair with Task #11 Trezor signing so the master seed never sits on the backend host.