Skip to content

Install with Docker Compose

The root compose.yaml includes one fragment per service from deploy/compose/*.yaml. Quick start walks through the demo profile end to end; this page covers bringing up the same services for a real site.

Every deployment needs the broker, the historian and the ingest/rollup pair:

Terminal window
docker compose up -d --wait rw-broker rw-historian rw-ingest
uv run rw db migrate --dsn "$RW_DSN"

The edge reader needs a site-specific config mounted read-only, and its own broker credential:

Terminal window
mkdir -p .rw/edge && cp <your-edge-config>.yaml .rw/edge/edge.yaml
docker compose --profile edge up -d --wait rw-edge

See Adapters for how to write that config for Modbus, OPC UA and MQTT sensor-node devices, and The Unified Namespace for the topic convention it publishes onto.

Terminal window
docker compose up -d --wait rw-detect
docker compose --profile demo up -d --wait rw-vision # only if cameras are configured

rw-detect needs the recipes/ and knowledge/ directories mounted read-only (already wired in deploy/compose/detect.yaml) so it can bind detectors to your signals — see Detectors.

Local inference (optional, needed for onboarding and Ask)

Section titled “Local inference (optional, needed for onboarding and Ask)”
Terminal window
uv run rw models pull <profile> --dest ./.rw/models
uv run rw infer args <profile> > .rw/infer-args/rw-infer.args
RW_PROFILE=<profile> docker compose up -d --wait rw-infer rw-embed

See Local inference & models for choosing a profile and Hardware sizing for the box this needs.

Terminal window
docker compose up -d --wait rw-app

Binds to 127.0.0.1:4441 by default; set RW_APP_BIND (and RW_APP_PORT) to change the bind address (and port) if the app needs to be reachable from elsewhere on the site’s own network. curl -s localhost:4441/api/health answers {"ok":true} once the app and its historian are up.

Settings adds people only from an admin’s session, so create the first admin from the command line once the historian is migrated:

Terminal window
uv run rw admin create --email you@plant.example --site plant-1 --site-name "Plant 1" \
--dsn "$RW_DSN"

It asks for the password without echo (or reads --password-file), grants the admin role on that site (created when missing; every site when --site is left out) and refuses while an admin already exists. An install from a bundle does this as its last step; see Air-gapped install.

Every inter-service credential (broker users, the historian password, the agent control plane’s token) is read from an environment variable or a file under /run/secrets, never hard-coded — set these once per site rather than relying on the compose files’ dev defaults. The comment block at the top of each deploy/compose/*.yaml fragment documents exactly which variables and secret files that service expects.