Skip to content

Environment Variables ​

Consolidated reference for all environment controls. The primary config file on macOS and Linux is /etc/edgecoder/edgecoder.env. See scripts/macos/payload/etc/edgecoder/edgecoder.env.example for a fully-annotated template.

Runtime mode ​

NODE_ENV (default development): production turns on the production-only checks listed under Startup validation.

VariableValuesDescription
EDGE_RUNTIME_MODEworker | coordinator | ide-provider | control-plane | inference | all-in-oneSelects which service the daemon runs as. Required.
HOST127.0.0.1Listen address for all HTTP services; set 0.0.0.0 in containers/Fly or for LAN multi-machine setups.

Worker identity and enrollment ​

VariableExampleDescription
AGENT_IDmac-worker-001Unique node identifier. Must match the enrolled node ID in the portal.
AGENT_OSmacos | ubuntu | debian | windows | iosOS label reported to coordinator.
AGENT_MODEswarm-only | ide-enabledWhether this agent also serves IDE inference requests.
AGENT_CLIENT_TYPEedgecoder-nativeRuntime flavor label. Keep default unless using a custom runtime.
AGENT_REGISTRATION_TOKEN(from Nodes page)Required for EDGE_RUNTIME_MODE=worker. Generated by node enrollment in the portal.

Coordinator configuration ​

VariableExampleDescription
COORDINATOR_URLhttps://coordinator.edgecoder.ioURL of the coordinator this agent connects to.
COORDINATOR_REGISTRATION_TOKEN(from Nodes page)Required for EDGE_RUNTIME_MODE=coordinator.
COORDINATOR_PUBLIC_URLhttps://coordinator.edgecoder.ioCoordinator's publicly-reachable URL (used by coordinator itself).
COORDINATOR_DISCOVERY_URLhttps://control.edgecoder.io/network/coordinatorsControl-plane endpoint for coordinator autodiscovery.
COORDINATOR_DISCOVERY_URLShttps://edgecoder-seed-eu.fly.devPortal: comma-separated coordinator URLs, tried in order. The first healthy one (/health/runtime) is cached for 60 s. Takes precedence over COORDINATOR_DISCOVERY_URL (#35).
COORDINATOR_BOOTSTRAP_URLShttps://coordinator.edgecoder.ioComma-separated fallback list.
COORDINATOR_HTTP_TIMEOUT_MS15000HTTP timeout for coordinator API calls (ms).
COORDINATOR_POST_RETRIES2Retry count for coordinator POST requests on transient failure.

Economy, payouts and receipts (coordinator) ​

VariableDefaultDescription
RATE_ORACLE_ENABLEDtrueEnable the BTC/USD rate oracle (median of sources, daily clamp). Set false to freeze class reference pricing.
RATE_RECALIBRATION_MS86400000How often the rate oracle recalibrates its per-class reference rates (ms; min 60000).
MARKET_DEFAULT_BID_PREMIUM_BPS1000Default order-book bid premium over the oracle reference, in basis points.
NETWORK_FEE_BPS500Network fee skimmed into the fee pool on each settled trade, in basis points.
HOST_HEARTBEAT_MS60000Interval at which a host reports its uptime/services heartbeat (ms; min 1000).
FEE_POOL_DISTRIBUTION_MS86400000Interval for distributing the network fee pool to hosts by uptime × services (ms; min 60000).
PAYOUT_AUTO_INTERVAL_MS21600000Interval for the LNURL auto-payout sweep (ms; min 60000).
RECEIPT_EPOCH_MS3600000Length of a signed-work-receipt Merkle epoch before it is sealed and anchored (ms).
RECEIPT_REPLICATION_MS60000How often sealed receipt epochs are replicated to peers (ms).

Model provider ​

VariableValues / ExampleDescription
LOCAL_MODEL_PROVIDERedgecoder-local | ollama-localInference backend. Use ollama-local when Ollama is installed.
OLLAMA_MODELqwen3.5:9bModel tag to use/pull when provider is ollama-local.
OLLAMA_AUTO_INSTALLtrue | falseAuto-pull the Ollama model on startup if not present.
OLLAMA_HOSThttp://127.0.0.1:11434Ollama daemon URL. Blank = default local host.

Mesh auth and security ​

VariableDescription
MESH_AUTH_TOKENShared mesh auth secret. Auto-provisioned by coordinator on successful registration if left blank.
COORDINATOR_MESH_TOKENAlias for MESH_AUTH_TOKEN. Keep aligned if both are set.
MESH_PEER_ALLOWLIST#52: comma-separated peerId:fingerprint@https://peer-url entries for the peer coordinators this coordinator trusts. @url pins the peer's endpoint, and gossip never changes it. In production every entry must have @url, or the coordinator refuses to start. fingerprint is the SHA-256 (hex) of the peer's SPKI public key. With the mesh token, a peer must also be on this list and sign its registration with that key. Results it forwards must be signed too. Required in production: without it, token-only peer registration and forwarded results are rejected. In dev an empty list keeps the old token-only behaviour.
COORDINATOR_PRIVATE_KEY_PEMEd25519 private key (PKCS#8 PEM) for this coordinator's mesh identity. Set it on every coordinator that peers, since a generated key changes on each restart and would drop off its peers' allowlists. Fingerprint for MESH_PEER_ALLOWLIST: node -e 'const c=require("crypto");const k=c.createPublicKey(process.env.COORDINATOR_PRIVATE_KEY_PEM);console.log(c.createHash("sha256").update(k.export({type:"spki",format:"der"})).digest("hex"))'
INFERENCE_AUTH_TOKENAuth token for the inference service API.
ADMIN_API_TOKENAdmin token for control-plane operator APIs.
PORTAL_SERVICE_TOKENInternal service token for portal ↔ coordinator/control-plane calls.
ENABLE_DEBUG_ROUTESSet 1 to register coordinator /debug/* routes (dev/e2e only; never registered in production).
PORTAL_ALLOW_OPEN_INTERNALSet 1 (non-production only) to leave portal /internal/* open when PORTAL_SERVICE_TOKEN is unset; otherwise those routes return 503.
REQUIRE_SIGNED_AGENT_REQUESTSDefault true, always true in production. Agent /heartbeat, /pull and /result must carry signed request headers (x-agent-id, x-signature, …). Set false only for local dev with legacy unsigned agents.

Result verification (#50, #106) ​

VariableDefaultDescription
RESULT_VERIFICATION_RATE0Base fraction of subtasks re-executed for verification. 0 = verification off (the default).
RESULT_VERIFICATION_ABANDON_PENALTY0.25Reputation lost for claiming a verification replica and never reporting it.
RESULT_VERIFICATION_REPLICA_CLAIM_TIMEOUT_MS300000A claimed replica with no report after this long is reassigned to an agent other than the abandoner(s).
RESULT_VERIFICATION_MAX_REASSIGNMENTS1How many times one sampled subtask's stalled replica is reassigned (0–10). After that the subtask waits for the overall timeout.
RESULT_VERIFICATION_INITIAL_REPUTATION0.5Reputation (0–1) of an agent id the coordinator has never seen. Below 1 so a caught agent can't regain full trust by re-registering; lower reputation means its results are re-executed more often.
RESULT_VERIFICATION_MAX_EXECUTIONS3Max executions of a sampled subtask (original + replicas), 2–3. Values above 3 are capped. At most this minus one replicas run per sampled subtask; whether winning replicas are paid is set by RESULT_VERIFICATION_MINT_REPLICA_REWARDS.
RESULT_VERIFICATION_MINT_REPLICA_REWARDSfalsePay winning verification replicas from newly minted compute credits (true/1/yes to enable). Off by default: only the original execution is paid, so verification doesn't add to the credit supply. Enabling minting requires Cody's approval. The coordinator logs a startup warning whenever RESULT_VERIFICATION_RATE is above 0, saying whether replicas are paid.

Portal and passkeys ​

VariableExampleDescription
PORTAL_PUBLIC_URLhttps://portal.edgecoder.ioPublic-facing portal URL (used in email links, OAuth redirect).
PORTAL_DATABASE_URLpostgres://...Portal PostgreSQL connection string.
PASSKEY_RP_IDportal.edgecoder.ioWebAuthn relying party ID (must match origin domain).
PASSKEY_RP_NAMEEdgeCoder PortalDisplay name for WebAuthn credential creation.
PASSKEY_ORIGINhttps://portal.edgecoder.ioExpected WebAuthn origin.
PASSKEY_CHALLENGE_TTL_MS120000Passkey challenge expiry (ms).
PORTAL_TRUST_FLY_CLIENT_IPunsetWhen true and Fly's runtime FLY_APP_NAME is set, the rate-limit client IP is read from the Fly-Client-IP header that the Fly edge proxy sets (Fly request headers). Otherwise it is the socket address, and X-Forwarded-* is never trusted (trustProxy: false). Keep unset until #31. Until it is set, all portal traffic on Fly shares the proxy's rate-limit bucket. PORTAL_TRUST_PROXY_HOPS is gone, because Fastify 5.12 ignores hop counts.
OAUTH_STATE_SECRET(32+ random chars)HMAC key for the browser-bound OAuth state cookie (__Host-oauth_state, #88). Required in production (at least 32 characters; the portal refuses to start without it). Set the same value on every instance. Outside production, unset means a random key per process.

Key provider and rotation ​

VariableValuesDescription
KEY_PROVIDERenv | hsm | tpm | secure-enclaveSigning key backend. Default: env.
HSM_PKCS11_LIB/usr/lib/libpkcs11.soPath to PKCS#11 shared library (required when KEY_PROVIDER=hsm).
HSM_SLOT_ID0HSM slot identifier.
HSM_PIN(secret)HSM user PIN.
KEY_ROTATION_DAYS90Maximum days between key rotations.

Bluetooth Local (BLE proxy — Mac IDE mode) ​

Used by the IDE provider server (EDGE_RUNTIME_MODE=ide-provider) to bridge the Mac-side IntelligentRouter to a nearby iPhone over Bluetooth.

VariableDefaultDescription
BT_PROXY_PORT11435Port the Swift edgecoder-ble-proxy companion listens on.
BT_PROXY_HOST127.0.0.1Host for the BLE proxy HTTP API. Always loopback in production.
BT_PROXY_URLhttp://127.0.0.1:11435Full URL the IntelligentRouter calls for bluetooth-local inference. Overrides BT_PROXY_HOST + BT_PROXY_PORT.
BT_STATUS_URL(auto-set)Status endpoint checked by the router to decide if BT is available. Set automatically from BT_PROXY_HOST:BT_PROXY_PORT.

The edgecoder-ble-proxy binary must be installed first:

bash
npm run build:ble-proxy
# Installs to /opt/edgecoder/bin/edgecoder-ble-proxy

Task and performance tuning ​

VariableDefaultDescription
MAX_CONCURRENT_TASKS1Parallel task limit per agent. Increase gradually only on machines with headroom.
PEER_OFFER_COOLDOWN_MS20000Cooldown between peer-direct offers while idle (ms). Lower = more aggressive.
DOCKER_PROBE_TIMEOUT_MS3000Timeout for the docker info availability probe; a hung daemon counts as unavailable. Result cached 30 s.

Inference service (port 4302) ​

The inference service checks these values at startup against inferenceConfigSchema (src/inference/config.ts). A missing or invalid value stops the service, and the error lists every problem at once. Empty values count as unset (#15).

VariableDefaultRule
INFERENCE_AUTH_TOKEN—Required. Shared token for /model/* writes and coordinator calls. At least 32 characters in production. Trimmed, so callers must send the trimmed value.
INFERENCE_REQUIRE_SIGNED_COORDINATOR_REQUESTSfalsetrue/false (also 1/0, yes/no; case-insensitive). When true, at least one trusted key must be configured.
INFERENCE_MAX_SIGNATURE_SKEW_MS120000Integer, 1000–3600000.
INFERENCE_NONCE_TTL_MS300000Integer, 1000–86400000.
INFERENCE_COORDINATOR_PEER_IDemptyMust be set together with INFERENCE_COORDINATOR_PUBLIC_KEY_PEM (both or neither).
INFERENCE_COORDINATOR_PUBLIC_KEY_PEMemptyThe trusted coordinator's public key.
INFERENCE_TRUSTED_COORDINATOR_KEYS_JSONemptyA JSON object of non-empty peerId → non-empty public key PEM. Anything else fails startup.
OLLAMA_HOSThttp://127.0.0.1:11434An http(s) URL.
OLLAMA_MODELqwen3.5:9bThe model that is active at startup.
OLLAMA_COORDINATOR_MODELqwen3.5:9b (decompose and reflect); falls back to OLLAMA_MODEL for chatThe model used for coordinator prompts.

IDE provider server (port 4304) ​

VariableDefaultDescription
IDE_PROVIDER_HOST127.0.0.1Bind address. A non-loopback value requires IDE_PROVIDER_TOKEN.
IDE_PROVIDER_TOKEN(from ~/.edgecoder/ide-token)Bearer token required on all routes except /health. If unset, the token file is created on first start (0600).
IDE_ALLOWED_ORIGINS(Tauri origins)Extra browser origins allowed; any other web Origin gets 403.
IDE_SHELL_ALLOWnpm,npx,node,python3,…Comma-separated binaries run_shell may run.
IDE_SHELL_AUTO_APPROVEunset1 skips the approval prompt for allowlisted shell commands (local opt-in).

iOS power telemetry (reported by iOS agents) ​

VariableDescription
IOS_ON_EXTERNAL_POWERtrue/false — device is charging
IOS_BATTERY_LEVEL_PCTBattery percentage (0–100)
IOS_LOW_POWER_MODEtrue/false — iOS Low Power Mode active
IOS_BATTERY_PULL_MIN_INTERVAL_MSThrottle between assignment attempts on battery
IOS_BATTERY_TASK_STOP_LEVEL_PCTMinimum battery level before stopping assignment

Bitcoin anchoring ​

VariableDefaultDescription
BITCOIN_ANCHOR_PROVIDERmockAnchoring provider: anchor-proxy, bitcoind, or mock (dev only). blockstream is rejected because it can't broadcast (#102).
BITCOIN_ANCHOR_CONFIRMATIONS6Confirmations before an anchor counts as anchored.
BITCOIN_ANCHOR_DAILY_BUDGET_SATS200000Daily anchoring budget: refuse a broadcast when (broadcasts in 24h + 1) × BITCOIN_ANCHOR_MAX_FEE_SATS exceeds it.
BITCOIN_ANCHOR_MAX_FEE_SATS20000Absolute fee cap per anchor tx.
BITCOIN_ANCHOR_MAINNETunsetSet to 1 to allow broadcasting on BITCOIN_NETWORK=bitcoin (opt-in).
BITCOIN_NETWORKsignetMust match across all coordinators in the mesh.
ANCHOR_PROXY_URL—URL of the anchor proxy service (when provider is anchor-proxy).
ANCHOR_PROXY_TOKEN—Bearer token for anchor proxy auth.
BITCOIND_RPC_URL—Direct bitcoind RPC URL (when provider is bitcoind).
BITCOIND_RPC_USER—RPC username.
BITCOIND_RPC_PASSWORD—RPC password.
BITCOIND_WALLET_NAME—Wallet name on the Bitcoin node.
ANCHOR_CONFIRMATION_POLL_MS60000Poll interval for pending anchors (ms).
STATS_ANCHOR_MIN_CONFIRMATIONS1Block confirmations before promoting anchor status.
ANCHOR_PROXY_PORT4310Listen port for the anchor proxy service.
MAX_BROADCASTS_PER_MINUTE10Rate limit for OP_RETURN broadcasts (anchor proxy).

Wallet and economy ​

VariableDescription
WALLET_DEFAULT_NETWORKDefault chain/network for wallet operations.
WALLET_SECRET_PEPPERServer-side pepper for wallet key derivation.
COORDINATOR_FEE_BPSCoordinator fee in basis points.
COORDINATOR_FEE_ACCOUNTFee recipient account address.
PAYMENT_INTENT_TTL_MSPayment intent expiry (ms).
PAYMENT_INTENT_EXPIRY_GRACE_MSDefault 120000. Extra time after the TTL before an unpaid intent is expired; reconcile always asks the Lightning node first.
LIGHTNING_PROVIDERlnd or cln. Required in production (coordinator refuses to boot otherwise, unless ECONOMY_PAYMENTS_ENABLED=false). Defaults to mock outside production.
LND_REST_URL / LND_MACAROON_HEXLND REST endpoint and invoice macaroon (required when LIGHTNING_PROVIDER=lnd).
CLN_REST_URL / CLN_API_TOKENCore Lightning REST endpoint and token (required when LIGHTNING_PROVIDER=cln).
ALLOW_MOCK_LIGHTNINGSet to 1 to allow the auto-settling mock provider in local dev. Never allowed in production; not needed when NODE_ENV=test.
PAYMENT_WEBHOOK_SECRETRequired in production. HMAC-SHA256 key for POST /economy/payments/webhook; senders must send x-payment-signature: sha256=<hex hmac of raw body> plus x-mesh-token (see API endpoints → Payment webhook signature). The webhook is only a hint — settlement is always confirmed with the Lightning node.
BLE_SYNC_MAX_CREDITS_PER_TXDefault 100. Max credits per offline BLE transaction accepted by /credits/ble-sync.
BLE_SYNC_ALLOW_V1Set 1 (non-production only, one release) to accept legacy v1 BLE signatures that do not cover credits.
ECONOMY_PAYMENTS_ENABLEDDefault true. Set 0, false, off or no (case-insensitive) to run without a Lightning node: no provider is created, and /economy/payments/* and POST /robot/tasks return 503.

Network and infrastructure ​

VariableDescription
NETWORK_MODEpublic_mesh or enterprise_overlay — mesh network policy mode.
CONTROL_PLANE_URLControl-plane service URL for coordinator/worker autodiscovery.
NODE_BINOverride Node.js binary path if auto-detection fails (macOS/Linux daemon).
DOCS_SITE_URLDocumentation site URL (used in portal links).
GITHUB_REPO_URLRepository URL for changelog/release links.
SUPPORT_EMAILContact address on the portal's privacy and terms pages (default support@edgecoder.io; plain address only) (#22).
MODEL_DOWNLOAD_DOMAINSComma-separated exact hostnames that signed model manifests may download from; replaces the default models.edgecoder.io,huggingface.co (#22). See Self-hosting.

Startup validation (#15) ​

Each service reads its environment once at startup through a zod schema. An invalid value (for example abc for an interval, maybe for a flag, or a URL without http(s)://) stops the service, and the error lists every problem at once. Empty values count as unset. A docs coverage test (tests/common/env-docs.test.ts) fails if a schema key is missing from this page.

ServiceSchemaProduction-only rules
inferencesrc/inference/config.tsINFERENCE_AUTH_TOKEN at least 32 characters
portalsrc/portal/config.tsPORTAL_SERVICE_TOKEN, WALLET_SECRET_PEPPER, RESEND_API_KEY, DOCS_SITE_URL required; CONTROL_PLANE_URL or COORDINATOR_DISCOVERY_URLS; CONTROL_PLANE_ADMIN_TOKEN when CONTROL_PLANE_URL is set; https for PORTAL_PUBLIC_URL, DOCS_SITE_URL and passkey origins
coordinatorsrc/swarm/coordinator-config.tsunchanged (requireProdEnv)
control-planesrc/control-plane/config.tsADMIN_API_TOKEN required in every environment

Portal: other validated settings ​

VariableTypeDefault
NODE_ENVstringdevelopment
PORTAL_EXTERNAL_HTTP_TIMEOUT_MSinteger ≥ 1007000
RESEND_FROM_EMAILstringunset
CONTROL_PLANE_ADMIN_TOKENstringunset
PORTAL_SESSION_TTL_MSinteger ms, 1000 to 31 days604800000
PORTAL_EMAIL_VERIFY_TTL_MSinteger ms, 1000 to 31 days86400000
WALLET_SEND_MFA_TTL_MSinteger ms, 1000 to 31 days600000
MOBILE_OAUTH_TOKEN_TTL_MSinteger ms, 1000 to 31 days300000
OAUTH_MICROSOFT_PROMPTstringselect_account
PASSKEY_ALLOWED_ORIGINSstringunset
COORDINATOR_OPERATIONS_OWNER_EMAILSstringunset
SYSTEM_ADMIN_EMAILSstringunset
COORDINATOR_ADMIN_EMAILSstringunset
IOS_OAUTH_CALLBACK_PREFIXstringedgecoder://oauth-callback
OAUTH_GOOGLE_CLIENT_IDstringunset
OAUTH_GOOGLE_CLIENT_SECRETstringunset
OAUTH_GOOGLE_AUTHORIZE_URLhttp(s) URLhttps://accounts.google.com/o/oauth2/v2/auth
OAUTH_GOOGLE_TOKEN_URLhttp(s) URLhttps://oauth2.googleapis.com/token
OAUTH_GOOGLE_USERINFO_URLhttp(s) URLhttps://openidconnect.googleapis.com/v1/userinfo
OAUTH_MICROSOFT_CLIENT_IDstringunset
OAUTH_MICROSOFT_CLIENT_SECRETstringunset
OAUTH_MICROSOFT_AUTHORIZE_URLhttp(s) URLhttps://login.microsoftonline.com/common/oauth2/v2.0/authorize
OAUTH_MICROSOFT_TOKEN_URLhttp(s) URLhttps://login.microsoftonline.com/common/oauth2/v2.0/token
OAUTH_MICROSOFT_USERINFO_URLhttp(s) URLhttps://graph.microsoft.com/oidc/userinfo
OAUTH_GITHUB_CLIENT_IDstringunset
OAUTH_GITHUB_CLIENT_SECRETstringunset

Coordinator: other validated settings ​

VariableTypeDefault
ROBOT_COORDINATOR_FEE_BPSinteger ≥ 0200
ROBOT_SWEEP_INTERVAL_MSinteger ≥ 186400000
ROBOT_MIN_SWEEP_SATSinteger ≥ 010000
ROBOT_TASK_DEFAULT_TIMEOUT_MSinteger ≥ 13600000
ROBOT_AUTO_SETTLE_DELAY_MSinteger ≥ 186400000
CONTRIBUTION_BURST_CREDITSinteger ≥ 025
MIN_CONTRIBUTION_RATIOnumber ≥ 01
ISSUANCE_WINDOW_MSinteger ≥ 186400000
ISSUANCE_RECALC_MSinteger ≥ 13600000
ISSUANCE_BASE_DAILY_POOL_TOKENSinteger ≥ 010000
ISSUANCE_MIN_DAILY_POOL_TOKENSinteger ≥ 02500
ISSUANCE_MAX_DAILY_POOL_TOKENSinteger ≥ 0100000
ISSUANCE_LOAD_CURVE_SLOPEnumber ≥ 00.35
ISSUANCE_SMOOTHING_ALPHAnumber ≥ 00.35
ISSUANCE_COORDINATOR_SHAREnumber ≥ 00.05
ISSUANCE_RESERVE_SHAREnumber ≥ 00.05
ANCHOR_INTERVAL_MSinteger ≥ 17200000
STATS_LEDGER_SYNC_INTERVAL_MSinteger ≥ 110000
STATS_ANCHOR_INTERVAL_MSinteger ≥ 1600000
AGENT_RATE_LIMIT_MAXinteger ≥ 030
AGENT_RATE_LIMIT_WINDOW_MSinteger ≥ 160000
SECURITY_NONCE_TTL_MSinteger ≥ 1300000
SECURITY_MAX_SKEW_MSinteger ≥ 1120000
TUNNEL_IDLE_TTL_MSinteger ≥ 190000
TUNNEL_MAX_RELAYS_PER_MINinteger ≥ 0120
RELAY_RATE_LIMIT_PER_10Sinteger ≥ 080
DIRECT_WORK_OFFERS_PER_10Sinteger ≥ 020
AGENT_ORCHESTRATION_ONLINE_WINDOW_MSinteger ≥ 1120000
ROBOT_QUEUE_ENABLEDtrue/falsefalse
REQUIRE_VERIFIED_AGENTStrue/falsefalse
INFERENCE_URLhttp(s) URLhttp://127.0.0.1:4302

Control plane: other validated settings ​

VariableTypeDefault
UI_RETIRE_REDIRECT_URLstringunset
ALLOWED_ADMIN_IPSstringunset
ALLOWED_UI_IPSstringunset

Observability (#14) ​

VariableDefaultDescription
LOG_LEVELinfopino log level for every service.
METRICS_TOKENunsetBearer token for Prometheus /metrics (inference: /metrics/prometheus). In production, /metrics is not served at all unless this is set. Outside production it is open.
REQUEST_ID_FORWARD_ORIGINSunsetExtra comma-separated origins that receive x-request-id on outbound calls. The service URLs (COORDINATOR_URL, CONTROL_PLANE_URL, INFERENCE_URL, PORTAL_SERVICE_URL, COORDINATOR_PUBLIC_URL, COORDINATOR_DISCOVERY_URLS) are included automatically; third-party APIs never get it.
SENTRY_DSNunsetOptional error tracking. Unset: off, nothing is loaded. Set: 5xx errors go to Sentry, tagged with service, route and request id, with no request bodies, headers or cookies. Needs @sentry/node in the image; if it's missing, the service logs one warning and runs without it.
SENTRY_ENVIRONMENTNODE_ENVSentry environment name.
SENTRY_RELEASEunsetSentry release (for example the git SHA).

Alerting on 5xx without Sentry ​

Every service exports edgecoder_http_requests_total{service,method,route,status}. Example Prometheus rules:

yaml
groups:
  - name: edgecoder-http
    rules:
      - alert: EdgeCoderHigh5xxRate
        # more than 5% of requests failing with 5xx for 10 minutes, per service
        expr: |
          sum by (service) (rate(edgecoder_http_requests_total{status=~"5.."}[5m]))
            / sum by (service) (rate(edgecoder_http_requests_total[5m])) > 0.05
        for: 10m
        labels: { severity: page }
      - alert: EdgeCoder5xxOnRoute
        # any single route returning 5xx steadily (catches a broken endpoint on a busy service)
        expr: sum by (service, route) (rate(edgecoder_http_requests_total{status=~"5.."}[5m])) > 0.1
        for: 15m
        labels: { severity: ticket }
      - alert: EdgeCoderMetricsMissing
        # the scrape itself failing usually means the service is down or METRICS_TOKEN is wrong
        expr: up{job=~"edgecoder-.*"} == 0
        for: 5m
        labels: { severity: page }

Scrape /metrics (inference: /metrics/prometheus) with authorization: Bearer $METRICS_TOKEN. route is the route pattern, so these rules stay low-cardinality.

Common profiles ​

bash
# 1) Standard mesh worker (most common)
EDGE_RUNTIME_MODE=worker
AGENT_ID=my-node-001
AGENT_OS=macos
AGENT_REGISTRATION_TOKEN=<from portal>
COORDINATOR_URL=https://coordinator.edgecoder.io

# 2) Worker + IDE-capable agent
EDGE_RUNTIME_MODE=worker
AGENT_MODE=ide-enabled

# 3) Dedicated coordinator
EDGE_RUNTIME_MODE=coordinator
COORDINATOR_REGISTRATION_TOKEN=<from portal>
DATABASE_URL=<postgres>

# 4) Local Ollama inference
LOCAL_MODEL_PROVIDER=ollama-local
OLLAMA_MODEL=qwen3.5:9b
OLLAMA_AUTO_INSTALL=true

Operational guidance ​

Production fail-fast (#5). With NODE_ENV=production, services refuse to boot when required secrets are empty (an empty token no longer means "auth off"):

  • coordinator: MESH_AUTH_TOKEN, PORTAL_SERVICE_URL, PORTAL_SERVICE_TOKEN, ADMIN_API_TOKEN, PAYMENT_WEBHOOK_SECRET, and LIGHTNING_PROVIDER unless ECONOMY_PAYMENTS_ENABLED=false
  • portal: PORTAL_SERVICE_TOKEN, WALLET_SECRET_PEPPER, RESEND_API_KEY (plus the existing passkey/URL checks)
  • inference: INFERENCE_AUTH_TOKEN
  • control-plane: ADMIN_API_TOKEN

Run a fly secrets list checklist against this list before any deploy.

  • Keep secrets in production secret stores (Fly Secrets, AWS SSM, etc.) rather than static env files.
  • On macOS, the env file is /etc/edgecoder/edgecoder.env (chmod 600, owned by root).
  • On Linux, same path — the systemd EnvironmentFile=-/etc/edgecoder/edgecoder.env directive loads it.
  • Review and rotate MESH_AUTH_TOKEN periodically.