Skip to main content

Environment variables

The node reads three kinds of environment variable:

  • Secrets, which have no config-file equivalent and must come from the environment or a secret manager.
  • Config overrides, NODE_-prefixed, which take precedence over the same field in config.yaml.
  • NODE_CONFIG, which selects the config file itself.
warning

The override list is a hand-maintained allowlist, not a mechanical mapping of every YAML field. Several blocks — zs.min_charge, zs.oracle, zs.rate_limits, zs.tool_pricing, zs.signing_balance, zs.coordinates, zs.payer_slot_cap, and everything under zs.models[] — are file-only. Setting a plausible-looking NODE_ZS_… name for one of those does nothing and reports nothing. If a setting isn't in a table below, put it in the file.

zs-node doctor lists any NODE_* variable that is overriding your file at runtime, which is the fastest way to catch a stale export.

Secrets — environment only​

Never put these in config.yaml.

VariableWhat it is
<NAME>_MNEMONICThe signing account's 25-word mnemonic. Any variable ending in _MNEMONIC is picked up — the label before the suffix is informational, and lookup is by derived address. OPERATOR_SIGNING_MNEMONIC is the conventional name. The node refuses to start without a mnemonic matching zs.signing_addr.
ZS_MNEMONIC_URLSComma-separated name=url pairs pointing at a cloud secret manager, in place of the above. Schemes: awssecretsmanager://, awsparamstore://, gcpsecretmanager://, azurekeyvault://, file://. Each backend uses its standard credential discovery (IAM role, ADC, managed identity).
NODE_LLM_OPENAI_API_KEYThe text upstream's API key. Required (non-empty) for provider: openai_passthrough even when your backend needs no authentication — export a placeholder if so. For kronk under any authorization mode except open, this must be an admin token.
NODE_IMAGE_LLM_OPENAI_API_KEYThe image upstream's API key for image_llm.provider: openai_passthrough. Independent of the text key, and it overrides image_llm.openai.api_key if both are set.
NODE_LLM_COMFYUI_CLOUD_API_KEYComfy Cloud API key. Required when image_llm.provider: comfyui_cloud; startup refuses an empty one.
NODE_ALGOD_TOKENAlgod API token, when your provider needs one.

Config file selection​

VariableEffect
NODE_CONFIGPath to the YAML config file. The --config flag wins over it; with neither set the node loads ./config.yaml.

server​

VariableOverrides
NODE_SERVER_LISTENserver.listen — the public bind address. Defaults to loopback; a serving node needs :9090.
NODE_SERVER_PRIVATE_LISTENserver.private_listen — /healthz, /livez, /metrics. Empty string colocates them on the public port.
NODE_SERVER_READ_TIMEOUTserver.read_timeout
NODE_SERVER_WRITE_TIMEOUTserver.write_timeout — must stay 0 for streaming.
NODE_SERVER_IDLE_TIMEOUTserver.idle_timeout
NODE_SERVER_SSE_KEEPALIVE_INTERVALserver.sse_keepalive_interval
NODE_SERVER_DRAIN_GRACEserver.drain_grace
NODE_SERVER_DRAIN_TIMEOUTserver.drain_timeout
NODE_SERVER_SHUTDOWN_TIMEOUTserver.shutdown_timeout

TLS and IP sync​

VariableOverrides
NODE_SERVER_TLS_MODEserver.tls.mode — off | manual | acme
NODE_SERVER_TLS_MANUAL_CERT_PATH / _KEY_PATHserver.tls.manual.*
NODE_SERVER_TLS_ACME_DOMAINSserver.tls.acme.domains (comma-separated)
NODE_SERVER_TLS_ACME_EMAILserver.tls.acme.email
NODE_SERVER_TLS_ACME_CACHE_DIRserver.tls.acme.cache_dir
NODE_SERVER_TLS_ACME_DIRECTORY_URLserver.tls.acme.directory_url
NODE_SERVER_TLS_ACME_PROPAGATION_DELAY / _TIMEOUTserver.tls.acme.propagation_*
NODE_SERVER_TLS_IP_SYNC_ENABLEDserver.tls.ip_sync.enabled
NODE_SERVER_TLS_IP_SYNC_IPV4 / _IPV6server.tls.ip_sync.ipv4 / .ipv6
NODE_SERVER_TLS_IP_SYNC_INTERVALserver.tls.ip_sync.interval
NODE_SERVER_TLS_IP_SYNC_TTLserver.tls.ip_sync.ttl
NODE_SERVER_TLS_IP_SYNC_URL_ENABLEDserver.tls.ip_sync.url.enabled

algod and logging​

VariableOverrides
NODE_ALGOD_NETWORKalgod.network — localnet | testnet | mainnet
NODE_ALGOD_ENDPOINTalgod.endpoint
NODE_ALGOD_TOKENalgod.token (see Secrets)
NODE_LOGGING_LEVELlogging.level
NODE_LOGGING_FORMATlogging.format

llm — text backend​

VariableOverrides
NODE_LLM_PROVIDERllm.provider
NODE_LLM_OPENAI_BASE_URLllm.openai.base_url
NODE_LLM_OPENAI_TIMEOUTllm.openai.timeout — must stay 0 for streaming.
NODE_LLM_OPENAI_TRANSLATE_RESPONSES_TO_CHATllm.openai.translate_responses_to_chat
NODE_LLM_OPENAI_MAX_RETRIESllm.openai.max_retries
NODE_LLM_OPENAI_RETRY_BASE_DELAY / _RETRY_MAX_DELAY / _RETRY_TOTAL_CAPthe transient-error retry budget
NODE_LLM_OPENAI_LOG_RAW_USAGEllm.openai.log_raw_usage — privacy-safe; counts only.
NODE_LLM_OPENAI_DEBUG_DUMP_ERRORSllm.openai.debug_dump_errors — dev only; writes decrypted content to stderr and is a hard startup error under tee.mode != none. See Privacy & non-retention.
NODE_LLM_HEALTH_CHECK_INTERVAL / _TIMEOUT / _FAILURE_THRESHOLDllm.health_check.*
NODE_LLM_LOCAL_BINARY_PATHllm.local.binary_path
NODE_LLM_LOCAL_HOST / _PORTllm.local.host / .port
NODE_LLM_LOCAL_PARALLEL_SLOTSllm.local.parallel_slots
NODE_LLM_LOCAL_STARTUP_TIMEOUTllm.local.startup_timeout
NODE_LLM_LOCAL_VERBOSE_LLAMAverbose llama-server output
NODE_LLM_VERTEXAI_PROJECT / _LOCATION / _ENDPOINT / _TIMEOUTllm.vertexai.*

llm.local.models[] and llm.vertexai.models[] are file-only.

image_llm — image backend​

VariableOverrides
NODE_IMAGE_LLM_PROVIDERimage_llm.provider
NODE_IMAGE_LLM_OPENAI_BASE_URLimage_llm.openai.base_url
NODE_IMAGE_LLM_COMFYUI_BASE_URLimage_llm.comfyui.base_url
NODE_IMAGE_LLM_COMFYUI_DATA_DIRimage_llm.comfyui.data_dir
NODE_IMAGE_LLM_COMFYUI_CLOUD_BASE_URLimage_llm.comfyui_cloud.base_url

zs — identity, admission, settlement​

VariableOverrides
NODE_ZS_OPERATOR_IDzs.operator_id
NODE_ZS_NODE_IDzs.node_id
NODE_ZS_OWNER_ADDR / NODE_ZS_SIGNING_ADDRthe on-chain address overrides
NODE_ZS_ESCROW_APP_IDzs.escrow_app_id
NODE_ZS_NFD_APP_ID / NODE_ZS_NFD_API_URLzs.nfd_app_id / zs.nfd.api_url
NODE_ZS_NFD_RECORD_NAMEzs.nfd_record_name
NODE_ZS_MAX_ACTIVE_TICKETSzs.max_active_tickets
NODE_ZS_TICKET_TTLzs.ticket_ttl
NODE_ZS_DEFAULT_EXPIRES_AFTERzs.default_expires_after
NODE_ZS_MEMPOOL_POLL_TIMEOUT / _INTERVALzs.mempool_poll_*
NODE_ZS_SETTLEMENT_DB_PATHzs.settlement_db_path
NODE_ZS_SETTLEMENT_WATCHDOG_SECONDSzs.settlement_watchdog_seconds
NODE_ZS_SETTLEMENT_LAPSE_GRACE_SECONDSzs.settlement_lapse_grace_seconds
NODE_ZS_SETTLEMENT_RETENTION / _RETENTION_INTERVALthe ledger janitor
NODE_ZS_RELAY_ONLYzs.relay_only
NODE_ZS_ALLOW_PRIVATE_RELAY_TARGETSzs.allow_private_relay_targets — localnet/dev only
NODE_ZS_INJECT_SAFETY_IDENTIFIERzs.inject_safety_identifier
NODE_ZS_SELF_EVICTION_ENABLED / _INTERVAL / _THRESHOLDzs.self_eviction.*

zs.reserve​

VariableOverrides
NODE_ZS_RESERVE_ENFORCE_INPUT_BUDGETzs.reserve.enforce_input_budget
NODE_ZS_RESERVE_INPUT_BUDGET_TOLERANCEzs.reserve.input_budget_tolerance
NODE_ZS_RESERVE_TOOL_HEADROOM_PER_ITERATIONzs.reserve.tool_headroom_per_iteration

zs.builtin_tools​

VariableOverrides
NODE_ZS_BUILTIN_TOOLS_ENABLEDthe whole subsystem
NODE_ZS_BUILTIN_TOOLS_MAX_ITERATIONSmax_iterations
NODE_ZS_BUILTIN_TOOLS_MAX_STALLED_ITERATIONSmax_stalled_iterations
NODE_ZS_BUILTIN_TOOLS_WEB_SEARCH_ENABLED / _MAX_RESULTS / _SAFE_SEARCH / _TIMEOUTweb_search.*
NODE_ZS_BUILTIN_TOOLS_WEB_READ_ENABLED / _MAX_BYTES / _MAX_DOWNLOAD / _MAX_CONCURRENT / _TIMEOUTweb_read.*
NODE_ZS_BUILTIN_TOOLS_WEB_READ_ALLOW_PRIVATE_TARGETSweb_read.allow_private_targets — localnet/dev only
NODE_ZS_BUILTIN_TOOLS_FAVICONS_ENABLED / _TIMEOUT / _MAX_BYTES / _CACHE_MAX_BYTES / _CACHE_TTLfavicons.*
NODE_ZS_BUILTIN_TOOLS_FAVICONS_ALLOW_PRIVATE_TARGETSfavicons.allow_private_targets — localnet/dev only
NODE_ZS_BUILTIN_TOOLS_IMAGE_SEARCH_ENABLED / _MAX_RESULTS / _SAFE_SEARCH / _TIMEOUTimage_search.* — the tool itself is force-disabled in code regardless.

tee​

VariableOverrides
NODE_TEE_MODEtee.mode
NODE_TEE_ATTESTATION_NRAS_URLtee.attestation.nras_url
NODE_TEE_ATTESTATION_REFRESH_INTERVALtee.attestation.refresh_interval
NODE_TEE_ATTESTATION_EVIDENCE_CACHE_PATHtee.attestation.evidence_cache_path
NODE_TEE_ATTESTATION_PCCS_URLtee.attestation.pccs_url

tee.dataflow deliberately has no environment form — see Confidential compute.

Where to put them​

Under systemd, zs-node install-service drops a 0600 /etc/zerosignal/secrets.env referenced by the unit's EnvironmentFile=. Under Docker, use --env-file or explicit -e flags. A common failure is exporting a variable in your interactive shell and expecting the service to see it — see Troubleshooting.