Deployment Modes

Applies to: ChengOS v0.2.0+ | Last verified: 2026-09-25 | Source: deploy/README.md, deploy/hybrid/, deploy/docker/, deploy/distributed/README.md, deploy/HARDENING.md

ChengOS supports three deployment shapes. They all read the same deploy/.env and are all driven by chengos.sh, so the choice is about where processes run — not about learning three different systems.

Choosing

Native (hybrid)DockerDistributed
Runs whereOne hostOne host, in containersTwo or more hosts
Needs DockerNoYesNo
Needs rootNo, with managed-processFor Docker itselfFor database install
ReproducibleVersion-pinned archiveVersion-pinned imagesVersion-pinned archive
OverheadLowestContainer layerLowest
Best forEvaluation, single-machine, no-root hostsProduction, reproducible installsPerformance-sensitive, separated datastores

If you are unsure: native to try it, Docker to run it. Reach for distributed only when you have a specific reason to separate the database host.

None of these is the single-user desktop app. ChengFlow Desktop (Windows .msi, Linux .deb on the release page) embeds the engine and a database in one window, needs no chengos.sh, and serves only the machine it runs on.

Native (hybrid)

The compiled cheng-api binary runs directly on the host and serves the web assets from the same package. No image pull, no container runtime.

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

The --db-install-mode choice is the one that matters:

ModeDatabases run asNeeds sudo
managed-process (default)Unprivileged user processes inside the install directoryNo
system-serviceapt-get-installed systemd servicesYes

managed-process is what lets you install ChengOS on a host where you have no administrative rights at all. system-service is the better choice when you want the databases managed by the OS, restarting on boot with everything else.

Mode scripts live in deploy/hybrid/ (start.sh, stop.sh, status.sh, generate-env.sh).

Docker

Every service runs as a Compose container, with all four images pinned by a single CHENGOS_VERSION.

./chengos.sh install --mode docker --with api,ui,app,cli
./chengos.sh start

Compose files in deploy/docker/:

FilePurpose
docker-compose.ymlThe default full deployment
docker-compose.binds.ymlOptional host-editable backend mounts
docker-compose.remote.ymlRemote/VPS override for reverse-proxy use

Remember that datastore hostnames change in this mode — postgres, redis, qdrant instead of 127.0.0.1. Full details in Docker deployment.

Distributed

Datastores on one host, the application on another, both native — Docker removed from the picture entirely to minimise runtime overhead.

On VPS A:

bash distributed/install_db.sh

The script prompts for VPS B's IP address, installs the databases natively, configures UFW, and generates secure passwords. It writes vps_b_env.txt containing the exact .env configuration VPS B needs.

On VPS B, unpack the release, copy vps_b_env.txt across, and start. The generated file is the authoritative handoff between the two hosts — do not hand-transcribe connection strings, since a mismatch between DATABASE_URL and the discrete DB_* variables produces failures that look unrelated to configuration.

Shared resources (.env.example, skills/, bin/, runtime/, logs/) stay at the deploy/ root and are shared by all three modes.

Selecting modules

--with takes any subset of api,ui,app,cli:

SelectionResult
api,ui,app,cliEverything
api,uiEditor only — no chat gateway, no terminal client
apiHeadless backend, driven by API or CLI from elsewhere
cliJust the terminal client, pointed at a remote server

Operating an installation

The same commands work in every mode:

./chengos.sh start      # start
./chengos.sh stop       # stop (optionally including databases)
./chengos.sh restart    # reload config and restart
./chengos.sh status     # PIDs/containers, ports, version, health, live logs
./chengos.sh update     # verified upgrade
./chengos.sh rollback   # restore the previous release
./chengos.sh doctor     # read-only check of what the host actually exposes
./chengos.sh uninstall  # tear down, keeping or erasing data

Run ./chengos.sh with no arguments for the interactive bilingual menu.

Exposing an installation

In every mode the API listens on loopback and only the frontends are meant to be reached: natively through BIND_ADDRESS=127.0.0.1, in Docker because Compose publishes every host port to 127.0.0.1. Nothing should face the internet except 80/443, held by one of:

EdgeInbound ports on the hostNotes
Cloudflare TunnelNonecloudflared connects out; recommended
Reverse proxy on the same host443The proxy reaches the frontends over loopback
Reverse proxy on another host443 on the proxyThe proxy-to-origin hop must be private or encrypted

Native installs also need UI_BIND / APP_BIND narrowed, because they default to every interface. Hardening a Public Deployment walks through each route; ./chengos.sh doctor verifies the result.

Next steps