Files
nick-doc/07 - Development/Environment Variables.md

25 KiB
Raw Blame History

title, tags
title tags
Environment Variables
development

Environment Variables

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 REMOVED REMOVED — MongoDB has been completely removed from the backend (v2.9.12). Do not set this variable.
DB_NAME backend REMOVED REMOVED — Was the Mongo database name; no longer used.
PG_URL backend REQUIRED postgres://amanat:...@postgres:5432/amanat_dev Drizzle runtime DSN. PostgreSQL is the only database layer; this must be set for the backend to start.
MIGRATION_PG_URL backend migration only postgres://amanat:...@postgres:5432/amanat_dev DSN used by backfill/migration scripts. Guarded by non-prod host allowlist.

PostgreSQL (Drizzle ORM) is the only database layer as of v2.9.12. MongoDB and Mongoose have been completely removed. 19 migrations (00000019) have landed covering 32 tables.

The following variables are also REMOVED and must not be set: MONGO_CONNECT_MODE, MONGO_URL, MONGODB_URI. Any .env file referencing them can have those lines deleted.


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.


Email / SMTP

Name Repo Required Default Example Purpose
SMTP_HOST backend smtp.zoho.com Outbound mail host
SMTP_PORT backend 465 TCP port (numeric)
SMTP_SECURE backend true true for TLS, false for STARTTLS
SMTP_USER backend no-reply@amn.gg SMTP username
SMTP_PASS backend SMTP password (or app password)
SMTP_FROM backend "AMN" <no-reply@amn.gg> Default From header

Payments — Request Network

Request Network is the current primary payment provider. See PRD - Request Network In-House Checkout, Request Network Integration Constraints, and Escrow Flow.

Name Repo Required Default Example Purpose
REQUEST_NETWORK_ENABLED backend optional true true Enables request.network as an available provider
REQUEST_NETWORK_API_KEY backend cli_... Request Network API credential
REQUEST_NETWORK_API_BASE_URL backend https://api.request.network https://api.request.network Request Network API base URL
REQUEST_NETWORK_ORIGIN backend FRONTEND_URL https://dev.amn.gg Origin sent to Request Network API
REQUEST_NETWORK_MERCHANT_REFERENCE backend <receiver>@eip155:56#...:<token> Encodes receiver, chain, payment reference, and token context
REQUEST_NETWORK_NETWORK backend optional bsc bsc Default checkout network
REQUEST_NETWORK_PAYMENT_CURRENCY backend optional USDT USDC Default checkout token symbol
REQUEST_NETWORK_WEBHOOK_CALLBACK_URL backend https://dev.amn.gg/api/payment/request-network/webhook Provider callback URL
REQUEST_NETWORK_WEBHOOK_SECRET backend HMAC secret for inbound webhook signatures
REQUEST_NETWORK_ALLOW_TEST_WEBHOOKS backend optional false false 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.
RPC_URL_CHAIN_97 backend optional https://bsc-testnet-rpc.publicnode.com https://bsc-testnet-rpc.publicnode.com Overrides the backend verifier RPC for BSC Testnet (bsc-testnet, bnb-testnet, numeric 97).
BSC_TESTNET_RPC_URL / BNB_TESTNET_RPC_URL backend optional RPC_URL_CHAIN_97 fallback https://... Alternate BSC Testnet RPC override names consumed by the legacy verifier path.
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 — AMN Pay Scanner

Backend scanner settings:

Name Repo Required Default Example Purpose
AMN_SCANNER_URL backend required when amn.scanner is enabled http://amn-scanner:8080 Internal scanner service base URL used by amnPayAdapter helpers.
AMN_SCANNER_API_KEY backend prod 64 hex chars Bearer token sent to scanner when scanner SCANNER_API_KEY is configured.
AMN_SCANNER_WEBHOOK_SECRET backend required when amn.scanner is enabled 64 hex chars Shared HMAC key used to verify scanner intent and balance-watch webhooks.
AMN_SCANNER_DEFAULT backend optional false true Makes AMN scanner the default pay-in provider where provider selection allows it.

Scanner service settings:

Name Repo Required Default Example Purpose
SCANNER_API_KEY scanner prod 64 hex chars Bearer token required for all scanner endpoints except /health.
BALANCE_WATCH_TICK_SEC scanner optional 60 60 How often the balance-watch scheduler queries for due watches.
BALANCE_WATCH_BATCH_SIZE scanner optional 50 50 Max due balance watches processed per scheduler tick.
DB_PATH scanner optional ./scanner.db /data/scanner.db SQLite state path for intents, checkpoints, and balance watches.
CHAINS_JSON_PATH scanner optional ./supported-chains.json /app/supported-chains.json Chain registry path.
TOKENS_JSON_PATH scanner optional ./tokens.json /app/tokens.json Token registry path used for token/tokenSymbol balance requests.
SCANNER_ENABLED_CHAINS scanner optional all configured chains 56,1,97 Restricts scanner startup to selected chain ids; dev includes chain 97 for BSC Testnet testing.
RPC_BSC / RPC_ETH / RPC_POLYGON / RPC_ARB / RPC_BASE scanner optional chain config provider URL EVM RPC overrides used by intent scanners and balanceOf reads.

Direct-address balance checks and watches currently support EVM ERC-20 only. Backend code should use checkScannerTokenBalance, createScannerBalanceWatch, and stopScannerBalanceWatch from amnPayAdapter.ts.


Repository Mode Flags (Migration Layer)

[!warning] These flags are obsolete as of v2.9.12. MongoDB and Mongoose have been completely removed. The repository factory returns Drizzle (PostgreSQL) repos exclusively. All domain stores are Postgres-only. The values mongo, dual, and DualWrite* are no longer valid — only postgres is valid, and it is the hardcoded default. These env vars are ignored at runtime and should not be set.

Name Repo Required Default Example Purpose
REPO_DEFAULT backend OBSOLETE REMOVED — Only postgres is valid; the factory always returns Drizzle repos.
REPO_USER backend OBSOLETE REMOVEDmongo and dual modes no longer exist.
REPO_PAYMENT backend OBSOLETE REMOVEDmongo and dual modes no longer exist.
REPO_POINTS backend OBSOLETE REMOVEDmongo and dual modes no longer exist.
REPO_MARKETPLACE backend OBSOLETE REMOVEDmongo and dual modes no longer exist.

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 2.8.94 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=5001
TRUST_PROXY=false

# Database (PostgreSQL only — MongoDB removed in v2.9.12)
PG_URL=postgres://amanat:secret@postgres:5432/amanat_dev

# Cache
REDIS_URI=redis://redis:6379

# Auth
JWT_SECRET=<openssl rand -hex 32>
JWT_EXPIRES_IN=1h
REFRESH_TOKEN_EXPIRES_IN=30d

# URLs
FRONTEND_URL=http://localhost:8083
BACKEND_URL=http://localhost:5001

# Rate limit
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100

# Files
MAX_FILE_SIZE=10485760
UPLOAD_PATH=/app/uploads

# SMTP
SMTP_HOST=smtp.example.com
SMTP_PORT=465
SMTP_SECURE=true
SMTP_USER=
SMTP_PASS=
SMTP_FROM="AMN <no-reply@amn.gg>"

# Payments
PAYMENT_PROVIDER=request.network
PAYMENT_ENABLED_PROVIDERS=request.network
PAYMENT_ROLLBACK_PROVIDER=request.network
REQUEST_NETWORK_ENABLED=true
REQUEST_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=false
PAYMENT_LEDGER_ENFORCEMENT=true
PAYMENT_RECONCILIATION_ENABLED=false
TREZOR_SAFEKEEPING_REQUIRED=false

# OpenAI (optional)
OPENAI_API_KEY=
OPENAI_DEFAULT_MODEL=gpt-4o-mini
OPENAI_MAX_TOKENS=1024
OPENAI_TEMPERATURE=0.7

# Seeding
AUTO_SEED_ON_START=true

# Wallets
ESCROW_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=56
DERIVED_DESTINATION_SWEEP_SIGNER=build-only
DERIVED_DESTINATION_MIN_SWEEP_AMOUNT=0
DERIVED_DESTINATION_SWEEP_INTERVAL_MS=300000
DERIVED_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_API_KEY=
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=false
PRICE_ORACLE_PROVIDERS=chainlink,offchain_fx
ORACLE_MAX_STALENESS_S=120
ORACLE_DISAGREE_BPS=100
DEPEG_HARD_CAP_BPS=500
QUOTE_VALIDITY_S=90
REQUOTE_RECONFIRM_BPS=50
OFFCHAIN_FX_URL=
OFFCHAIN_FX_REQUEST_TIMEOUT_MS=8000
CHAINLINK_RPC_1=
CHAINLINK_RPC_56=

# OAuth
GOOGLE_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.