The proxy-router is configured through .env (or container env vars). This page documents every variable. The canonical .env.example lives in the repo at proxy-router/.env.example and the full annotated dump at docs/proxy-router.all.env.
Defaults below are from the source of truth (proxy-router/internal/config/config.go). When in doubt, the source wins.

Conflicting / overlapping variables — read this first

Several pairs of variables look like they do “the same thing.” They don’t. The proxy-router resolves each pair with a specific precedence rule, and getting it wrong is a common cause of “I changed the env but nothing happened.”
For every *_CONTENT*_PATH pair below, the *_CONTENT variable is a one-shot file seeder, not a runtime override. It only takes effect when the corresponding file does not exist. After the first successful start the file exists, and changing the *_CONTENT env on subsequent runs has no effect until you delete the file at *_PATH.
SituationWhat the proxy-router does
File at COOKIE_FILE_PATH already existsReads the file. COOKIE_CONTENT is silently ignored.
File does not exist + COOKIE_CONTENT is setWrites COOKIE_CONTENT to the file (username:password\n), then reads it.
File does not exist + COOKIE_CONTENT is unsetGenerates a random 32-char password for admin, writes it to the file.
Source: proxy-router/internal/system/auth.go (EnsureConfigFilesExist). Practical implications
  • For TEE / Akash / ephemeral container deployments, set COOKIE_CONTENT once on first start; the file gets seeded inside the volume and persists.
  • To rotate credentials on a self-hosted node, use the POST /auth/users endpoint (or edit the cookie file in place) — changing COOKIE_CONTENT after first start does nothing.

MODELS_CONFIG_PATHMODELS_CONFIG_CONTENT

SituationWhat the proxy-router does
File at MODELS_CONFIG_PATH already existsReads the file. MODELS_CONFIG_CONTENT is silently ignored.
File does not exist + MODELS_CONFIG_CONTENT is setWrites MODELS_CONFIG_CONTENT to the file, then reads it.
File does not exist + MODELS_CONFIG_CONTENT is unsetLogs a warning and runs with an empty model registry.
Source: proxy-router/internal/config/models_config.go (ModelConfigLoader.Init). Practical implications
  • Use MODELS_CONFIG_CONTENT (single-line JSON) in TEE/Akash deployments where you can’t mount a volume.
  • To update models on a self-hosted node, edit the JSON file directly and restart — don’t bump MODELS_CONFIG_CONTENT. See models-config.json.

AGENT_CONFIG_PATHAGENT_CONFIG_CONTENT

Same *_CONTENT-only-seeds-the-file rule as the two above. Source: proxy-router/internal/config/agents_config.go.

AUTH_CONFIG_FILE_PATH (no inline twin)

Path to proxy.conf, which holds rpcauth= and rpcwhitelist= lines. There is no AUTH_CONFIG_CONTENT env — the file is built at runtime by the proxy-router itself when you add users via POST /auth/users. For TEE / ephemeral deployments, proxy.conf is created on first start (with the admin entry derived from the cookie file) and managed via the API afterwards.

WALLET_PRIVATE_KEY ↔ system keychain

SituationWhat the proxy-router does
WALLET_PRIVATE_KEY is setUses it. The keychain is not read.
WALLET_PRIVATE_KEY is unset and the OS supports a keychain (macOS)Reads / writes the key from the system keychain.
NeitherRefuses to start signing transactions; read-only operations still work.
APP_RESET_KEYCHAIN=true wipes the macOS keychain entry on start (use with care).

WEB_PUBLIC_URL fallback

If WEB_PUBLIC_URL is unset, the proxy-router synthesizes http://localhost:<port-from-WEB_ADDRESS>. For provider deployments where consumers must reach you over the public internet, always set this explicitly to your public URL (e.g. https://provider.example.com). The TLS-pinning step in TEE attestation reads this URL.

ETH_NODE_USE_SUBSCRIPTIONSETH_NODE_POLLING_INTERVAL

Not a precedence pair, but easy to misconfigure:
  • ETH_NODE_USE_SUBSCRIPTIONS=true → expects a WSS ETH_NODE_ADDRESS (e.g. wss://...). Polling interval is irrelevant.
  • ETH_NODE_USE_SUBSCRIPTIONS=false (default) → expects an HTTPS ETH_NODE_ADDRESS and uses ETH_NODE_POLLING_INTERVAL (default 10 seconds).
Mismatch (e.g. subscriptions=true with HTTPS endpoint) makes the node fail to receive blockchain events even though startup may look healthy.

PROXY_STORE_CHAT_CONTEXT is TEE-frozen

In the -tee image this is hard-coded false at build time and cannot be overridden at runtime. Setting it in the env has no effect inside a TEE deployment. See TEE reference.

Application

VariableDefaultNotes
APP_RESET_KEYCHAINfalseSet true to reset the macOS keychain entry on start
AUTH_CONFIG_FILE_PATH./proxy.confPath to the auth config file (no inline twin)
COOKIE_FILE_PATH./.cookiePath to admin cookie file
COOKIE_CONTENT(unset)Seeds the cookie file on first start only. See precedence above.

Blockchain

VariableDefaultNotes
ETH_NODE_CHAIN_ID8453 (mainnet) / 84532 (testnet)BASE chain ID
ETH_NODE_ADDRESS(unset, falls back to built-in public RPC round-robin)RPC endpoint URL (HTTPS or WSS — must match ETH_NODE_USE_SUBSCRIPTIONS). Set explicitly for any real deployment — the public round-robin fallback is rate-limited and unreliable; missed events break the node silently.
ETH_NODE_LEGACY_TXfalseSet true to disable EIP-1559
BLOCKSCOUT_API_URLhttps://base.blockscout.com/api/v2Block explorer API
EXPLORER_RETRY_DELAY5Delay between explorer retries (seconds)
EXPLORER_MAX_RETRIES5Max explorer retries
ETH_NODE_USE_SUBSCRIPTIONSfalsetrue to use WSS subscriptions; false for HTTP polling
ETH_NODE_POLLING_INTERVAL10Polling interval (seconds, only when ETH_NODE_USE_SUBSCRIPTIONS=false)
ETH_NODE_MAX_RECONNECTS30Max reconnect attempts

Environment

VariableDefaultNotes
ENVIRONMENTdevelopmentUse production in deployments

Marketplace

VariableDefaultNotes
DIAMOND_CONTRACT_ADDRESSmainnet 0x6aBE1d282f72B474E54527D93b979A4f64d3030a; testnet 0x6e4d0B775E3C3b02683A6F277Ac80240C4aFF930Diamond marketplace contract
MOR_TOKEN_ADDRESSmainnet 0x7431aDa8a591C955a994a21710752EF9b882b8e3; testnet 0x5C80Ddd187054E1E4aBBfFCD750498e81d34FfA3MOR ERC-20 token
WALLET_PRIVATE_KEY(unset)Wallet private key. Falls back to system keychain when unset. See precedence above.

Logging

VariableDefaultNotes
LOG_COLORfalseColored console output
LOG_FOLDER_PATH(unset)If set, also write logs to files in this directory
LOG_IS_PRODfalseProduction log format
LOG_JSONfalseJSON-formatted log lines
LOG_LEVEL_APPwarnApp-level log level: debug info warn error dpanic panic fatal
LOG_LEVEL_TCPwarnTCP layer log level
LOG_LEVEL_ETH_RPCwarnEthereum RPC log level
LOG_LEVEL_STORAGEwarnBadger storage log level
For TEE images logging is frozen to production / JSON / minimal at build time — these vars have no effect inside a -tee image.

Network ports & URLs

VariableDefaultNotes
WEB_ADDRESS0.0.0.0:8082Bind for the HTTP/Swagger API
WEB_PUBLIC_URLhttp://localhost:<WEB_ADDRESS port>Public-facing URL of the API. Set explicitly for any provider that consumers must reach.
PROXY_ADDRESS0.0.0.0:3333Bind for the consumer-to-provider TCP proxy

Proxy state & configs

VariableDefaultNotes
MAX_CACHED_DESTS5Max cached provider destinations
PROXY_STORAGE_PATH./data/badger/Local Badger / runtime state
PROXY_STORE_CHAT_CONTEXTtruePersist chat context. Frozen false in -tee images.
PROXY_FORWARD_CHAT_CONTEXTtruePrepend stored history to prompts
MODELS_CONFIG_PATH./models-config.jsonSee models-config. See precedence above.
MODELS_CONFIG_CONTENT(unset)Seeds the models config file on first start only. See precedence above.
AGENT_CONFIG_PATH(built-in default)Local agent registry path
AGENT_CONFIG_CONTENT(unset)Seeds the agent config file on first start only. Same rules as the models pair.
RATING_CONFIG_PATH./rating-config.jsonSee rating-config

Timeouts & retries

VariableDefaultNotes
LLM_TIMEOUT(depends on release)P-Node → backend LLM timeout (streaming + non-streaming)
CNODE_PNODE_TIMEOUT(depends on release)Per-attempt timeout for C-Node waiting for P-Node first response
CNODE_PNODE_MAX_RETRIES(depends on release)Max retries for C-Node → P-Node read timeout (chat / embeddings)
CNODE_PNODE_AUDIO_MAX_RETRIES(depends on release)Max retries for audio transcription / speech routes
For exact defaults check the source of truth (config.go) — these can change between releases as we tune the network.

TEE (Phase 1 + Phase 2 attestation)

These are only consulted when at least one model in the marketplace is tee-tagged. Otherwise they are unused.
VariableDefaultNotes
TEE_PORTAL_URLhttps://secretai.scrtlabs.com/apiSecretAI Portal used to verify raw TDX CPU quotes
TEE_IMAGE_REPOghcr.io/morpheusais/morpheus-lumerin-node-teeGHCR repo where the consumer-side P-Node attestation fetches the signed golden manifest via cosign
ARTIFACT_REGISTRY_URLhttps://raw.githubusercontent.com/scrtlabs/secretvm-verify/main/artifacts_registry/tdx.csvSecretVM TDX artifact registry CSV (MRTD + RTMR0-2 lookup)
ARTIFACT_REGISTRY_REFRESH_INTERVAL1hHow often the proxy-router re-downloads the artifact registry
See TEE overview and TEE reference.

System tuning (optional sysctl tweaks)

These map to OS-level adjustments and only apply when SYS_ENABLE=true.
VariableDefaultNotes
SYS_ENABLEfalseSet true to apply the values below at startup
SYS_LOCAL_PORT_RANGE1024 65535
SYS_NET_DEV_MAX_BACKLOG100000
SYS_RLIMIT_HARD524288
SYS_RLIMIT_SOFT524288
SYS_SOMAXCONN100000 (Linux) / 2048 (Darwin/macOS)
SYS_TCP_MAX_SYN_BACKLOG100000

Mainnet vs testnet quick switch

Comment / uncomment the appropriate block in .env:
# MAINNET
ETH_NODE_CHAIN_ID=8453
DIAMOND_CONTRACT_ADDRESS=0x6aBE1d282f72B474E54527D93b979A4f64d3030a
MOR_TOKEN_ADDRESS=0x7431aDa8a591C955a994a21710752EF9b882b8e3
BLOCKSCOUT_API_URL=https://base.blockscout.com/api/v2

# TESTNET (Base Sepolia)
# ETH_NODE_CHAIN_ID=84532
# DIAMOND_CONTRACT_ADDRESS=0x6e4d0B775E3C3b02683A6F277Ac80240C4aFF930
# MOR_TOKEN_ADDRESS=0x5C80Ddd187054E1E4aBBfFCD750498e81d34FfA3
# BLOCKSCOUT_API_URL=https://base-sepolia.blockscout.com/api/v2

Full annotated dump

For the complete annotated reference (every variable, every example value), see docs/proxy-router.all.env in the repo.