Profiles

Turn on optional services with COMPOSE_PROFILES: model serving and the nsjail code sandbox in Standalone, extra workers and admin UIs in Distributed.

In this page

A profile is a Docker Compose tag on a service that stays off until you ask for it. Name the profile in COMPOSE_PROFILES in .env, and the next ./bin/install or docker compose up -d starts that service too. Every setup is complete without a profile: they add capabilities, not the core of the app. Standalone and Distributed have their own profiles, and Helm uses chart values instead.

📝
TL;DR

Standalone runs three containers: ml adds model serving and sandbox adds the nsjail code executor. Distributed always runs serving and the code executor: workers, observability and peerdb add per-queue workers, the Temporal UI and the PeerDB UI, and all adds all of them. Set profiles in .env, not only on the command line.

%%{init: {"flowchart": {"curve": "linear"}}}%%
flowchart TD
  accTitle: Optional profiles in the two Docker Compose setups
  accDescr: Standalone's app, postgres and clickhouse gain serving with the ml profile and code-executor with the sandbox profile. Distributed gains per-queue workers with workers, the Temporal UI and admin tools with observability, and the PeerDB UI with peerdb.
  S["Standalone: app, postgres, clickhouse"] -->|"ml"| SM["serving"]
  S -->|"sandbox"| SS["code-executor with nsjail"]
  D["Distributed: one container per service"] -->|"workers"| DW["Seven per-queue workers"]
  D -->|"observability"| DO["Temporal UI and admin tools"]
  D -->|"peerdb"| DP["PeerDB UI"]

Standalone profiles

Standalone runs app, postgres and clickhouse. Two profiles add one container each, and neither publishes a host port.

ProfileAddsDownloadTurn it on for
mlserving, the embedding model serverabout 450 MBEmbedding-based evals, knowledge bases, ground truth and Vector DB columns
sandboxcode-executor, the nsjail sandbox (privileged)about 185 MBJavaScript code evals, and code evals isolated from each other

ml: model serving

serving runs the embedding models behind embedding-based evals, knowledge bases, ground truth and Vector DB columns (and, with an Enterprise Edition license, Error Feed clustering). Without it those features report that model serving is not deployed, everything else works, and the Agent fixer (evals) row on the first-run setup screen reads Optional. A knowledge-base file uploaded while serving is off is marked Failed: turn on ml, then upload the file again.

It needs a few more GB of memory once its models load. The image runs PyTorch on the CPU. On a host with an NVIDIA GPU, set SERVING_VERSION=vX.Y.Z-gpu (or latest-gpu) in .env for the CUDA build, and give the serving container the GPU with a deploy.resources.reservations.devices entry in docker-compose.override.yml. The -gpu image is linux/amd64 only and about 3.3 GB.

sandbox: isolated code evals

Without this profile, custom code evals run in the sandbox built into app. Python evals run there as an unprivileged user with resource limits. JavaScript evals do not run: the app image has no Node.js, so each one fails with an error that names the sandbox profile.

With sandbox, every run gets its own nsjail jail, with its own processes and a read-only view of the filesystem. It needs a host that allows privileged containers. Turn it on for an install shared by people who must not trust one another. Isolate the code executor covers what each sandbox allows.

Neither sandbox closes the network. In the built-in one, even where Landlock (Linux 6.7 or later) limits evals to TCP ports 80 and 443, UDP and whatever your network serves on those ports stay reachable. On older kernels an eval can reach Postgres and ClickHouse over the Docker network, and ClickHouse has no password while CH_PASSWORD is empty, as it is in a .env copied by hand from .env.example. Set it as in Secrets the installer generates.

Turn a profile on

Add the profiles to .env, comma-separated:

COMPOSE_PROFILES=ml,sandbox

Then apply it:

./bin/install          # or: docker compose up -d

Note

Set COMPOSE_PROFILES in .env, not only with --profile or in your shell. The app reads it from .env to send code evals to the nsjail code-executor instead of its built-in sandbox, and ./bin/install warns when sandbox is set in your shell but not in .env.

Turn a profile off

Remove it from COMPOSE_PROFILES in .env and run docker compose up -d. Compose leaves the containers of a profile that is no longer active running, and --remove-orphans does not count them as orphans, so remove the container yourself:

docker compose --profile sandbox rm -sf code-executor   # after turning sandbox off
docker compose --profile ml rm -sf serving              # after turning ml off

Otherwise the privileged code-executor keeps running although the app no longer uses it.

Distributed profiles

Distributed runs 31 containers without a profile: 22 long-running services, including serving, code-executor, the all-queue worker and PeerDB replication, and 9 one-shot setup jobs. Four profiles add optional services:

ProfileAddsWhere to reach it
workersworker-default, worker-tasks-s, worker-tasks-l, worker-tasks-xl, worker-trace-ingestion, worker-agent-compass, worker-simulation-runnerNothing to open
observabilitytemporal-ui, temporal-admin-toolsTemporal UI at http://localhost:8085 (TEMPORAL_UI_PORT)
peerdbpeerdb-uiPeerDB UI at http://localhost:3001 (PEERDB_UI_PORT)
allAll ten of the aboveBoth UIs

Combine them with commas, for example COMPOSE_PROFILES=workers,observability, then run ./bin/install or docker compose up -d. No other service needs the ones these profiles add in order to start. PeerDB replication runs in Distributed with or without peerdb: the profile adds only its UI.

Installs made before Standalone became the default used the name full. It still works and adds the same services as all. A .env that sets it only to get PeerDB can drop it, since replication runs without a profile. On Standalone full has no effect.

Warning

The Temporal UI and the PeerDB UI listen on all interfaces and ask for no password: the Temporal UI has no sign-in, and the compose file sets no password for the PeerDB UI. Anyone who can reach those ports (8085 and 3001 by default) can view and change workflows and mirrors. Turn on observability, peerdb, all or full only on a trusted network, or block those ports at a firewall as in Security & TLS.

Per-queue workers

The workers profile gives each Temporal task queue its own worker, with its own concurrency limits. Hosted voice simulations run only in worker-simulation-runner, so they need workers or all. System configuration covers TEMPORAL_ALL_QUEUES=false, which leaves each queue to its own worker, and the limits of each worker.

worker-simulation-runner is linux/amd64 only. On an Apple Silicon or Linux arm64 host, Docker runs it under emulation (Rosetta 2 on Docker Desktop, qemu-user-static on Linux), which is slower.

observability and peerdb

temporal-ui and temporal-admin-tools (Temporal’s command-line tools) are for inspecting workflow state when a background job misbehaves. peerdb-ui is the web UI of PeerDB, which copies Postgres changes into ClickHouse.

Note

./bin/dev --distributed, the Distributed development stack, runs the per-queue workers, the Temporal UI and admin tools and the PeerDB UI whatever COMPOSE_PROFILES says. See Other ways to run it.

Helm

The Helm chart has no profiles. The same choices are chart values:

ValueDefaultWhat it does
serving.enabledfalseRuns the embedding model server, as ml does in Standalone
codeExecutor.enabledfalseRuns the nsjail sandbox for custom code evals. It needs privileged pods
worker.queues[]Gives a busy queue its own Deployment, as workers does in Distributed

See Configure on the Helm page.

Checking what will run

These commands read the configuration only, so they work with the stack down:

docker compose config --profiles                              # every profile name in the file
COMPOSE_PROFILES=ml,sandbox docker compose config --services  # Standalone: what these profiles start
COMPOSE_PROFILES=all docker compose config --services         # Distributed: what the all profile starts

On Distributed they read COMPOSE_FILE from .env, which ./bin/install --distributed writes. Without it, add -f docker-compose.distributed.yml. On Distributed the profile list includes full, the older name of all. Standalone with no profile lists app, postgres and clickhouse.

Note

A profile is not a launch mode. The choice the first-run setup screen asks you to make changes how its checks are reported, never which services run.

Dive deeper

Was this page helpful?

Questions & Discussion