Run a fleet

Join nodes

Turn any machine into a node, with a join token or by approval.

A node needs only outbound access to the edge on ports 7233 and 7443. It creates its own key when it joins; the key never leaves the machine.

With one command

On the web UI's Nodes page, Add nodes creates a join token and shows one command for Linux and macOS:

Terminal
curl -fsSk https://edge.example.com:7443/v1/ca.crt -o /tmp/oz0-ca.crt \
  && echo '<sha256 of the CA>  /tmp/oz0-ca.crt' | (sha256sum -c --quiet || shasum -a 256 -c --quiet) \
  && curl -fsS --cacert /tmp/oz0-ca.crt https://edge.example.com:7443/install.sh | sh -s -- --token 'K10...'

It downloads the cluster's CA certificate, checks it against the hash in the command, and fetches the install script over TLS that trusts only that CA, so nothing it runs can have been changed on the way. The script downloads orchestrator-zero-node for the machine's platform and checks its digest, installs it in /usr/local/bin (or ~/.local/bin without root), joins, and starts the node in the foreground. On its first start the node downloads the runtime from the edge too.

install.sh takes --name, --data-dir, --dir for the binary, and --no-run to install and join only. The edge serves what make dist built; see Install.

With a join token

A token admits nodes without an operator approving each one. Create it on the operator side:

Terminal
orchestrator-zero token create --tenant default --max-uses 10 --ttl 24h --label gpu=a100

The token is shown once. It carries the cluster's CA hash, so the node can check the server before it sends anything. On the machine:

Terminal
OZ0_JOIN_TOKEN='K10...' orchestrator-zero-node join --server https://edge.example.com:7443
orchestrator-zero-node run

Labels on the token are given to every node that joins with it.

By approval

Without a token, the node waits until an operator accepts it, as with salt-key -a. Get the CA hash first:

Terminal
orchestrator-zero cluster info                 # shows the CA hash

On the machine:

Terminal
orchestrator-zero-node join --server https://edge.example.com:7443 --ca-hash sha256:...

The node prints its fingerprint and waits. On the operator side, compare the fingerprint and accept it:

Terminal
orchestrator-zero node list --pending
orchestrator-zero node accept node-7f3a01b2c4d5 --tenant default --label zone=eu

node reject refuses it instead.

What run does

orchestrator-zero-node run runs in the foreground. On first start it installs a pinned uv and a managed Python, and the runtime: the bundle given with --runtime-bundle, or else the one the edge serves, checked against its digest. Then it:

  • opens the control stream to the edge and keeps it open,
  • runs a local Temporal proxy and a local LLM proxy, both holding the node's certificate,
  • starts the agent runtime, which polls oz0.default, the node's own node.<id> queue, the queues of the agents it has, and any queues listed in its queues label,
  • downloads, builds and starts the plugins its tenant has installed for it.

Certificates renew themselves. A blocked node stops its runtime and asks again every ten seconds.

Labels and queues

Labels are key-value pairs: gpu=a100, zone=eu-north, team=data. They decide which plugins a node gets (plugin install --select) and which agents it may run (requires.labels in an agent). Set them on the token or at node accept.

The special label queues lists extra task queues the node polls, for example --label queues=reports,batch. Only operators set it.

Run a node as a service

Built-in service installation (systemd, launchd and Windows services) is planned. Until then, use your service manager. A systemd unit, for example:

/etc/systemd/system/orchestrator-zero-node.service
[Unit]
Description=Orchestrator Zero node
After=network-online.target
Wants=network-online.target

[Service]
User=oz0
ExecStart=/usr/local/bin/orchestrator-zero-node run
Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

Join once as the same user (sudo -u oz0 orchestrator-zero-node join ...) before you enable the service, and run nodes as a user without root: plugins run with the node's permissions.

Small machines

A Raspberry Pi with a 64-bit OS is a linux/arm64 node like any other, good for agents that drive local hardware or run light tools. Give it a label such as device=pi and require it in the agents that need it.

Copyright © 2026