Native Deployment

Applies to: ChengOS v0.2.0+ | Last verified: 2026-09-25 | Source: deploy/hybrid/start.sh, deploy/hybrid/status.sh, deploy/hybrid/stop.sh, deploy/chengos.sh, deploy/.env.example

Native — "hybrid" in the scripts — runs the compiled cheng-api binary directly on the host, with no container runtime. It is the mode to choose when you want the lowest overhead, or when you have no root on the machine at all.

Deployment Modes compares it with Docker and distributed; this page is how to run it.

Install

./chengos.sh install --mode native --db-install-mode managed-process --with api,ui,app,cli
./chengos.sh start
./chengos.sh status

chengos.sh also runs as an interactive menu with no arguments, in English or Chinese. The non-interactive commands are install, start, stop, restart, status, version, update, rollback, doctor, cloudflare, and uninstall.

Modules are selected with --with: api, ui, app, cli, plus redis and qdrant for the optional infrastructure. The installer offers full, minimal (Postgres + API + UI), or custom.

status exits non-zero when the API is not serving, deliberately, so it works as a health probe in a monitoring script.

The database decision

DB_INSTALL_MODE is the choice that shapes everything else:

ModeDatabases run asNeeds sudo
managed-process (default)Unprivileged user processes inside the install directoryNo
system-serviceSystem packages plus systemd servicesYes

managed-process creates a PostgreSQL data directory with initdb inside the install tree and starts it with pg_ctl on port 5432, as your own user. Nothing touches the system package manager and nothing needs elevation. This is what makes ChengOS installable on a shared host or a locked-down VM.

system-service installs the packages and enables them with systemctl enable --now postgresql (and valkey-server when Redis is enabled), so the databases start with the machine. start.sh checks for sudo up front rather than failing halfway.

Switching from system-service to managed-process stops and disables the system services first, so the two do not both try to hold port 5432.

If initdb and postgres are not on the host at all, the script fails with an explicit message rather than guessing — install the Postgres client tools and rerun.

Override per run:

./chengos.sh start --db-install-mode system-service

Configuration

Everything reads deploy/.env. start.sh copies .env.example to .env on the first run and then stops, telling you to edit it — it will not start with placeholder secrets.

For native mode the essentials are:

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

DB_INSTALL_MODE=managed-process
ENABLE_REDIS=false
ENABLE_QDRANT=false

PORT=19225
API_PORT=19225
UI_PORT=8080
APP_PORT=5055
BIND_ADDRESS=127.0.0.1    # the API: this host only
UI_BIND=0.0.0.0           # the UI server: narrow this before going public
APP_BIND=0.0.0.0          # the app server: likewise

CREDENTIAL_MASTER_KEY_1=<64 hex chars>   # openssl rand -hex 32
JWT_SECRET=<64 hex chars>

Hosts are 127.0.0.1 in native mode, not the compose service names used in Docker. That is the most common copy-paste error between modes. See Storage, Redis & Vector Configuration.

ENABLE_REDIS and ENABLE_QDRANT default to false: a minimal install runs on PostgreSQL alone. Turn on Redis when you need scheduling or agent memory, and Qdrant when you need RAG.

deploy/generate-env.sh produces a .env with generated secrets instead of placeholders.

The hardened topology

A native host runs three services that are not equally public:

ServiceListens onReached by
cheng-apiBIND_ADDRESS = 127.0.0.1The UI and app servers, which proxy /api and /ws; the CLI and health checks on this host
ui-serverUI_BINDYour reverse proxy or cloudflared
app-serverAPP_BINDYour reverse proxy or cloudflared

The API never needs another address: even a remote CLI or desktop client should reach it through the proxy's 443, where /api is forwarded. UI_BIND and APP_BIND default to 0.0.0.0, so a fresh install serves the frontends on every interface until you change them:

.env is never overwritten by an upgrade, so an older installation keeps BIND_ADDRESS=0.0.0.0 and may lack UI_BIND / APP_BIND entirely until you add them. The frontends print their effective proxy trust set at startup. The full procedure, for both the tunnel and the proxy routes, is in Hardening a Public Deployment.

Optional: a local decision model. With LAYA_ENABLED=true and LAYA_BIN plus LAYA_MODEL_PATH or LAYA_MODELS_DIR set, start.sh also launches laya serve on LAYA_PORT (1215), verifies each model file against its pinned SHA-256, and warms it up; status and stop include it. See Decision Providers & TypeSafe Jev.

Layout

start.sh creates and uses:

<install-root>/
  bin/cheng-api          the binary
  .env
  logs/                  cheng-api.log, ui-server.log, app-server.log
  runtime/               pid files, database data directory
  skills/                skill packages
  ui/  app/              served frontend assets

Log paths can be overridden with CHENG_API_LOG_FILE, CHENG_UI_LOG_FILE, and CHENG_APP_LOG_FILE.

Day-to-day operation

./chengos.sh start                 # start selected modules
./chengos.sh status                # process status and version, non-zero if the API is down
./chengos.sh restart               # stop then start with the recorded module set
./chengos.sh stop                  # stop services
./chengos.sh version
./chengos.sh update                # scripts and package
./chengos.sh update --scripts-only # scripts only
./chengos.sh doctor                # read-only exposure report; non-zero on a problem
./chengos.sh uninstall

stop takes an option controlling whether the databases stop with the application — leave them running if something else uses them.

status reports the installed version and whether a newer release is available; the update flow is covered in Upgrades & Rollback.

The scripts underneath live in deploy/hybrid/ (start.sh, stop.sh, status.sh, generate-env.sh) and can be called directly, for example bash hybrid/start.sh --with api,ui. Prefer chengos.sh: it records the installed mode and module set so restart and update do the right thing without repeating the flags.

Installing from source

If the install root contains chengflow/ and chengflow-ui/, the installer detects a developer workspace and compiles from source instead of unpacking a release archive. On a server you almost certainly want the release package; on a development machine this is the convenience.

Troubleshooting

SymptomCause
No .env file foundFirst run created it; edit it and rerun
Postgres will not startPort 5432 already held — often a leftover system-service install
Postgres tools are not installedinitdb/postgres missing; install the client tools
status says not serving, no logCheck logs/cheng-api.log; usually a bad DATABASE_URL or a missing secret
Scheduling does nothingENABLE_REDIS=false
RAG nodes fail to connectENABLE_QDRANT=false, or QDRANT_URL pointing at 6333 instead of 6334
system-service install fails earlyIt requires sudo and checks up front
Remote CLI cannot connect to port 19225Expected: the API is loopback-only. Connect through the reverse proxy on 443
status reports UI NOT RESPONDINGIt prints the address it probed; if that differs from UI_BIND, .env changed without a restart
EADDRNOTAVAIL on startUI_BIND / APP_BIND names an address that is not on this host

Next steps