Environment Variable Reference

Applies to: ChengOS v0.2.0+ | Last verified: 2026-09-25 | Source: deploy/.env.example, deploy/generate-env.sh, crates/cheng-api/src/services/env_settings/registry.rs, config/decision_providers.toml

Every ChengOS deployment mode — native, Docker, and distributed — reads the same deploy/.env file. This page is the parameter dictionary. For how to actually deploy, see Install ChengOS and Docker deployment.

Start from the template rather than an empty file:

cp deploy/.env.example deploy/.env

chengos.sh install and generate-env.sh fill in generated secrets and derive ports and paths, so in most cases you edit only what you want to differ from the defaults.

.env is instance-owned: an upgrade never overwrites it. Defaults introduced by a newer release — such as the loopback API binding in v0.2.0 — apply to new installs only, so compare your file against the new .env.example after each upgrade.

Required secrets

These have placeholder values in the template. An installation that leaves them unchanged is not secure. Generate each one before exposing the system.

VariableGenerate withNotes
CREDENTIAL_MASTER_KEY_1openssl rand -hex 32Encrypts every stored credential. Losing it makes stored credentials unrecoverable; changing it strands the existing ones.
JWT_SECRETopenssl rand -hex 32Signs API access tokens. Changing it invalidates every issued session.
POSTGRES_PASSWORDopenssl rand -hex 16Must match the password inside DATABASE_URL.
REDIS_PASSWORDopenssl rand -hex 16Must match the password inside REDIS_URL.

Datastore connections

DATABASE_URL=postgres://tianai_db:<password>@127.0.0.1:5432/master_router
REDIS_URL=redis://:<password>@127.0.0.1:6379
QDRANT_URL=http://127.0.0.1:6334

The hostname depends on the deployment mode: 127.0.0.1 for native and managed-process installs, the Compose service names postgres / redis / qdrant for Docker, and your own host for distributed installs.

Agent memory nodes read the connection as discrete values rather than a URL, so these must stay consistent with DATABASE_URL and REDIS_URL:

VariableDefault
DB_HOST / DB_PORT127.0.0.1 / 5432
DB_NAME / DB_USER / DB_PASSWORDmaster_router / tianai_db / —
REDIS_HOST / REDIS_PORT / REDIS_DB127.0.0.1 / 6379 / 0

Pool tuning is available for both: DATABASE_MAX_CONNECTIONS (10), DATABASE_MIN_CONNECTIONS (1), DATABASE_CONNECTION_TIMEOUT (30), and the matching REDIS_MAX_CONNECTIONS, REDIS_MIN_CONNECTIONS, REDIS_CONNECTION_TIMEOUT.

Ports and server binding

VariableDefaultService
PORT / API_PORT19225API backend and WebSocket
UI_PORT8080Visual editor and admin console
APP_PORT5055Chat app and mobile H5
BIND_ADDRESS127.0.0.1API bind address
UI_BIND / APP_BIND0.0.0.0Interface the native UI / app servers listen on

The API stays on loopback in every supported layout: the UI and app servers proxy /api and /ws to it, and the CLI and health checks dial 127.0.0.1. 0.0.0.0 would put the API on the network beside the hardened frontends rather than behind them. A remote CLI or desktop client should go through your reverse proxy on 443 instead.

UI_BIND / APP_BIND select an interface; they are not access control. Use 127.0.0.1 when the proxy is on the same host, or a private/VPN address of this host when it is elsewhere.

Docker ignores all three: docker-compose.yml publishes host ports to 127.0.0.1 only and pins BIND_ADDRESS=0.0.0.0 inside the API container, because the UI container must reach it over the Compose network.

Edge and proxy trust

VariableDefaultNotes
TRUSTED_PROXY_IPSemptyComma-separated addresses or CIDRs of proxies allowed to report a visitor's real IP. Loopback and RFC 1918 peers are trusted without being listed; a proxy on a public or CGNAT (100.64.0.0/10) address must be listed, or every visitor shares one rate-limit bucket.
TRUST_CLOUDFLAREfalseAlso trust Cloudflare's ranges and read CF-Connecting-IP. Toggle with ./chengos.sh cloudflare on|off.
CSP_CONNECT_SRC_EXTRAemptyExtra origins, space-separated, for the frontends' CSP connect-src.

See Hardening a Public Deployment for how these fit together.

Release pinning

VariableDefaultNotes
CHENGOS_VERSIONlatestThe single release pin for all four Docker images. Set an exact version in production.
CHENGOS_<SERVICE>_IMAGEunsetPer-image override for private registries. Any override disables coordinated release updates.
CHENGOS_IMAGEchengos/chengos:latestLegacy alias for older Compose overlays. Prefer CHENGOS_VERSION.

Runtime behaviour

VariableDefaultNotes
RUN_MIGRATIONStrueApply database migrations on startup. Ignored while demo mode is on.
CHENG_DEMO_MODEfalseFail-closed public demo allowlist. Initialize the demo user before enabling. See demo mode.
CHENG_DEMO_USER_EMAILunsetThe ordinary, non-admin account demo visitors are signed in as.
RUST_LOGinfoLog level.
RUST_BACKTRACE1Include backtraces in error logs.
DB_INSTALL_MODEmanaged-processmanaged-process (user sandbox, no root) or system-service (apt + systemd, needs sudo).
ENABLE_REDISfalseTurn on when using agent memory.
ENABLE_QDRANTfalseTurn on when using RAG retrieval.

Scheduler

Governs timed and triggered workflow runs.

VariableDefaultNotes
SCHEDULER_ENABLEDtrueMaster switch.
SCHEDULER_NODE_IDnode-1Must be unique per instance in a multi-instance deployment.
SCHEDULER_MAX_CONCURRENCY8Simultaneous scheduled executions.
SCHEDULER_HOT_WINDOW_SECS60Look-ahead for imminent jobs.
SCHEDULER_WARM_WINDOW_SECS300Look-ahead for upcoming jobs.
SCHEDULER_SWEEPER_INTERVAL_SECS30Sweep interval for due jobs.
SCHEDULER_LOCK_TIMEOUT_SECS60Lock lease before another instance may claim a job.

CORS

CORS_PERMISSIVE=false
CORS_ALLOWED_ORIGINS=

CORS is deny-by-default, because every supported deployment is same-origin: the UI and app servers proxy /api and /ws themselves. Fill CORS_ALLOWED_ORIGINS (comma-separated) only when a browser on a different origin must call the API. CORS_PERMISSIVE=true allows any origin, logs a warning on every start, and is for local experiments only.

Workspaces and sandboxes

VariableNotes
CHENG_CLI_ALLOWED_ROOTSColon-separated absolute directories usable as CLI sandboxes. CLI sessions are disabled entirely if this is unset. The CLI and API must see these paths in the same filesystem namespace.
CHENG_WORKSPACE_ROOTBase directory for code_shell / code_python when no CLI sandbox is present. Defaults to {repo_root}/workspaces or ./workspaces.
SKILLS_DIRSkill library location. Default ./skills.
NODE_SKILLS_DIRPer-node skill definitions. Docker default /app/node_skills.
CHENG_GLOBAL_CONFIG_DIRShared shortcuts.yaml and presets.yaml. Docker /app/config; native auto-detects. Per-workspace configs override these.
TEMPLATE_WORKFLOWS_DIRRead-only built-in workflow templates installed into new workspaces on bootstrap. Docker /app/workflow-templates; native auto-detects.

Agent tool approval — see Tool-call Approval Policy:

VariableNotes
CHENG_FILE_OPS_PROTECTED_PATTERNSComma-separated gitignore-style patterns added to the built-in protected paths. It can only add.
CHENG_TRUSTED_AUTOMATION_POLICY_FILEJSON file of scoped entries that let named workflows run deletes, moves, and rollbacks unattended.
CHENG_WORKSPACE_PROCESS_APPROVAL_DISABLEDtrue removes the approval gate on workspace shell and test runs for the whole deployment. Trusted automation servers only.

Decision models

Settings for the typed decision providers behind ai/decision_branch. They are read once at startup. Details: Decision Providers & TypeSafe Jev.

VariableDefaultNotes
JEV_API_KEYunsetDeployment-managed TypeSafe Jev key, used by nodes that select no credential. Routed request text is sent to TypeSafe.
JEV_DEFAULT_MODELjev-1.13.0Jev model when neither the node nor its credential pins one. Use an exact version with a calibration profile.
CHENG_DECISION_PROVIDERS_TOMLunsetReplacement for the shipped decision_providers.toml. An invalid file is ignored.
CHENG_DECISION_CALIBRATION_TOMLunsetReplacement for the shipped calibration profiles. An invalid file is ignored.
LAYA_ENABLEDfalseEnable the local Laya decision model (laya serve).
LAYA_PORT1215Laya on the API host's loopback. Never 8080, which UI_PORT uses.
LAYA_ENDPOINTunsetFull Laya address instead, e.g. http://host.docker.internal:1215 from Docker.
LAYA_TRUSTED_NETWORKfalseAllow a non-loopback plain-http LAYA_ENDPOINT.
LAYA_DEFAULT_MODELmultilingualLaya family when a node names none.
LAYA_API_KEYunsetBearer token shared with laya serve.
LAYA_ARTIFACT_SHA256, LAYA_ARTIFACT_SHA256_<FAMILY>unsetSHA-256 pin of the served GGUF; calibration applies only to a pinned file.
LAYA_BIN, LAYA_MODEL_PATH, LAYA_MODELS_DIR, LAYA_DEVICE, LAYA_LD_LIBRARY_PATHunsetNative mode only: let hybrid/start.sh launch and verify laya serve. Leave empty to run it yourself.

Jev endpoints and decision timeouts are TOML settings in decision_providers.toml, not environment variables.

Code execution and model endpoints

VariableDefaultNotes
CHENG_ENABLE_CODE_PYTHONtrueEnables the tools/code_python node.
CHENG_ENABLE_CODE_JStrueEnables the tools/code_js node.
ALLOW_PRIVATE_LLM_ENDPOINTStruePermits model endpoints on private network addresses, such as a local Ollama. Set false to block requests to private ranges.

Optional integrations

MCP — MCP_ENABLED (false) mounts the app-level MCP server at /mcp. MCP_SERVER_TOKEN sets a static bearer token; leave it unset to use database-backed MCP tokens, which is the preferred mode. MCP_GATEWAY_PORT_START (9100) is the base port for per-workflow dynamic servers.

OAuth2 — client IDs and secrets come from each provider's app console: OAUTH2_OPENAI_*, OAUTH2_ANTHROPIC_*, OAUTH2_GOOGLE_*, OAUTH2_GITHUB_*, OAUTH2_MICROSOFT_*. PKCE providers need no client secret; GitHub OAuth apps generally do. OAUTH2_REDIRECT_URI must match the redirect URI registered with the provider exactly.

Email — EMAIL_ENABLED (false), then SMTP_HOST, SMTP_PORT, SMTP_USERNAME, SMTP_PASSWORD, SMTP_FROM, and PASSWORD_RESET_BASE_URL. Required for password reset mail.

Public URLs — used by Docker deployments to tell the frontends where to reach the backend: UI_API_BASE_URL (/api/v1), UI_WS_URL (/ws), APP_API_BASE_URL, APP_WS_URL (/ws/executions), APP_CHANNEL_ID, APP_BOUND_WORKFLOW_ID, and the externally visible PUBLIC_UI_URL, PUBLIC_APP_URL, PUBLIC_API_URL.

CLI — CHENG_SERVER_URL is the server the cheng client connects to. Docker deployments default it to http://api:3000.

Next steps