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
PG_URL
backend
conditional
—
postgres://amanat:...@postgres:5432/amanat_dev
Drizzle runtime DSN. Required before importing PG-backed code such as quoteRepo; does not cut over app domains by itself.
MIGRATION_PG_URL
backend
migration only
—
postgres://amanat:...@postgres:5432/amanat_dev
DSN used by backfill/migration scripts. Guarded by non-prod host allowlist.
In docker-compose.production.yml the Mongo service is mongodb and is reachable as mongodb://mongodb:27017 from the backend container.
[!warning] Postgres cutover flags
REPO_* flags exist in the backend repository factory, but broad services still call Mongoose models directly on integrate-main-into-development@3a50dc4. Do not assume setting REPO_DEFAULT=pg or REPO_PAYMENT=pg fully moves live traffic to Postgres without service wiring and verification. See Postgres Runtime Cutover Status.
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.
Allows explicit Request Network test webhooks only for controlled smoke tests
ESCROW_WALLET_ADDRESS
backend
✅
—
0xa304…
Master escrow address used by payments service
RECEIVER_WALLET_ADDRESS
backend
optional
—
0x…
Used by alternative payout flows
Historical SHKeeper keys
SHKEEPER_* variables may still appear in legacy migration docs or old .env files. They are not the current primary checkout path and should not be used for new payment work unless a deliberate legacy-record reconciliation task requires them.
Payments — Provider Selection
Name
Repo
Required
Default
Example
Purpose
PAYMENT_PROVIDER
backend
optional
request.network
request.network
Active provider for new payment intents
PAYMENT_DEFAULT_PROVIDER
backend
optional
request.network
request.network
Fallback alias when PAYMENT_PROVIDER is unset
PAYMENT_ENABLED_PROVIDERS
backend
optional
request.network
request.network
Comma-separated providers allowed at runtime
PAYMENT_ROLLBACK_PROVIDER
backend
optional
request.network
request.network
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
chain floor
Fallback minimum confirmations for unknown chains. Known chains use built-in acceptance floors unless a higher admin-configured value exists.
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.
Repository Mode Flags (Migration Layer)
Name
Repo
Required
Default
Example
Purpose
REPO_DEFAULT
backend
optional
mongo
dual
Fallback repository mode for domains that do not set their own flag. Current broad runtime services are not yet wired through the factory.
REPO_USER
backend
optional
REPO_DEFAULT or mongo
dual
Intended user/auth repository mode. Requires service wiring before it affects normal requests.
REPO_PAYMENT
backend
optional
REPO_DEFAULT or mongo
dual
Intended payment/ledger repository mode. Current payment APIs still call Mongoose directly.
REPO_POINTS
backend
optional
REPO_DEFAULT or mongo
dual
Intended points/referral repository mode. Current points service still calls Mongoose directly.
REPO_MARKETPLACE
backend
optional
REPO_DEFAULT or mongo
dual
Intended purchase request / seller offer repository mode. Current marketplace services still call Mongoose directly.
Payments — Oracle Quoting / Depeg Protection
Name
Repo
Required
Default
Example
Purpose
ORACLE_QUOTING_ENABLED
backend
optional
false
true
Enables server-authoritative seller-offer quoting on /api/payment/request-network/intents.
PRICE_ORACLE_PROVIDERS
backend
optional
chainlink,offchain_fx
chainlink,offchain_fx
Ordered provider list used by the quote engine.
ORACLE_MAX_STALENESS_S
backend
optional
120
120
Rejects stale FX/token rates.
ORACLE_DISAGREE_BPS
backend
optional
100
100
Maximum allowed provider disagreement before the quote is blocked.
DEPEG_HARD_CAP_BPS
backend
optional
500
500
Blocks automatic quoting beyond this stablecoin depeg.
QUOTE_VALIDITY_S
backend
optional
90
90
Quote expiry window.
REQUOTE_RECONFIRM_BPS
backend
optional
50
50
Frontend/backend threshold for buyer reconfirmation after a material re-quote.
OFFCHAIN_FX_URL
backend
conditional
—
https://fx.example/rates
Required when offchain_fx is enabled for fiat currencies without Chainlink coverage.
OFFCHAIN_FX_REQUEST_TIMEOUT_MS
backend
optional
8000
8000
HTTP timeout for the off-chain FX provider.
CHAINLINK_RPC_1
backend
conditional
—
https://...
Ethereum RPC for Chainlink stablecoin/USD reads.
CHAINLINK_RPC_56
backend
conditional
—
https://...
BSC RPC for Chainlink stablecoin/USD reads.
Payments — Wallet UI (frontend)
Name
Repo
Required
Default
Example
Purpose
NEXT_PUBLIC_DEPAY_INTEGRATION_ID
frontend
legacy only
—
1330e2d3-…
Historical 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>"# PaymentsPAYMENT_PROVIDER=request.network
PAYMENT_ENABLED_PROVIDERS=request.network
PAYMENT_ROLLBACK_PROVIDER=request.network
REQUEST_NETWORK_ENABLED=trueREQUEST_NETWORK_API_KEY=REQUEST_NETWORK_API_BASE_URL=https://api.request.network
REQUEST_NETWORK_ORIGIN=https://dev.amn.gg
REQUEST_NETWORK_MERCHANT_REFERENCE=REQUEST_NETWORK_NETWORK=bsc
REQUEST_NETWORK_PAYMENT_CURRENCY=USDC
REQUEST_NETWORK_WEBHOOK_CALLBACK_URL=https://dev.amn.gg/api/payment/request-network/webhook
REQUEST_NETWORK_WEBHOOK_SECRET=REQUEST_NETWORK_ALLOW_TEST_WEBHOOKS=falsePAYMENT_LEDGER_ENFORCEMENT=truePAYMENT_RECONCILIATION_ENABLED=falseTREZOR_SAFEKEEPING_REQUIRED=false# 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# Master sweep wallet private key (pays gas for permit() + transferFrom() on non-BSC# chains; sends BNB gas top-ups on BSC). Should be a dedicated low-balance hot wallet# — NOT the same key used for escrow release/refund.SWEEP_MASTER_PRIVKEY=# BSC gas top-up thresholds (in BNB). If derived address BNB balance is below MIN, top up by TOP_UP.SWEEP_GAS_MIN_BNB=0.001
SWEEP_GAS_TOP_UP_BNB=0.002
# AMN Pay Scanner (replaces Request Network for pay-in detection)AMN_SCANNER_URL=AMN_SCANNER_WEBHOOK_SECRET=AMN_SCANNER_DEFAULT=false# Oracle quoting / stablecoin depeg protection# Keep disabled until feeds and the off-chain FX source are configured.ORACLE_QUOTING_ENABLED=falsePRICE_ORACLE_PROVIDERS=chainlink,offchain_fx
ORACLE_MAX_STALENESS_S=120ORACLE_DISAGREE_BPS=100DEPEG_HARD_CAP_BPS=500QUOTE_VALIDITY_S=90REQUOTE_RECONFIRM_BPS=50OFFCHAIN_FX_URL=OFFCHAIN_FX_REQUEST_TIMEOUT_MS=8000CHAINLINK_RPC_1=CHAINLINK_RPC_56=# 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.