Skip to content

Workers ​

A Toki network worker is a process that connects outward over TLS to a coordinator and runs the commands it is assigned. It has no listening port, so the machine needs no SSH server, no inbound firewall rule and no CI runner.

You can run a worker in two ways:

  • Standalone: start toki-worker yourself with a JSON configuration.
  • Managed: let Tama download, configure and supervise it.

Both use the same protocol, durable queue, identities and receipts.

Standalone worker ​

sh
toki-worker --config toki-worker.json

Without --config, toki-worker reads toki-worker.json from the current directory. The combined binary has the same command as toki worker --config FILE.

Configuration ​

json
{
  "coordinatorUrl": "https://toki.example:7443",
  "serverName": "toki.example",
  "caPem": "-----BEGIN CERTIFICATE-----\nYOUR CA CERTIFICATE\n-----END CERTIFICATE-----",
  "token": "YOUR_64_HEX_WORKER_TOKEN",
  "workDir": "./workspace",
  "stateDir": "./worker-state",
  "reconnectDelayMs": 1000
}
FieldMeaning
coordinatorUrlThe coordinator's advertised HTTPS endpoint.
serverNameThe TLS name (or IP) the coordinator's certificate must match.
caPemThe coordinator's CA certificate.
tokenA worker credential issued with toki daemon issue --role worker.
workDirWorkspace root. Commands outside it are refused.
stateDirLaunch journal and results; keep it across restarts.
reconnectDelayMsDelay before reconnecting, 50–60000 ms (default 1000).
buildsOptional. Enables committed-source builds; see below.

Relative directories resolve against the config file. The file holds a credential: keep it private to the user that runs the worker.

The worker requires HTTPS with the supplied CA and server name. Authentication, role and protocol refusals stop it. Temporary network failures reconnect automatically, including after a laptop sleeps.

Build settings ​

To accept committed-source builds, add a builds object:

json
"builds": {
  "targetDir": "D:/toki/targets",
  "jobs": 8,
  "memoryBytes": 34359738368,
  "cpuRate": 2500,
  "labels": ["build-host"],
  "repositories": ["https://github.com/your-org/your-repo.git"]
}
FieldMeaning
targetDirAbsolute directory for the worker's leased Cargo target slots.
jobsCargo parallelism, 1–256.
memoryBytesOptional memory limit per command (Windows and Linux only).
cpuRateOptional CPU limit in hundredths of a percent of the machine, 1–10000 (Windows and Linux only).
labelsLabels clients can select as class:<label>.
repositoriesHTTPS allowlist of repositories the worker may fetch. Must not be empty.
toolchainRootOptional absolute directory of toolchain manifests; see provisioned execution.
ginOptional Gin snapshot providers; see Gin sources.

Each build gets a disposable checkout and one leased target slot. Git fetches only the requested commit. Clients cannot supply local paths or mirrors.

Trust the coordinator

The worker runs the commands its coordinator sends. This is process ownership, not a security sandbox: only connect to a coordinator you trust.

Stopping and signals ​

Ctrl+C cancels the active command and stops the worker. On Unix, SIGTERM and terminal hang-up take the same path. The cancelled command's process tree is stopped and reaped.

Restart-safe execution ​

Each assignment is one attempt. Before launching, the worker flushes a record to stateDir/launched.jsonl, and it refuses to launch the same assignment twice.

A durable build keeps running when the connection drops or the coordinator restarts. Its outcome is journalled in stateDir/results when it ends. After the worker reconnects, the coordinator queries that journal and publishes the result once, without a second launch. While such an attempt is still running, the reconnected worker answers outcome queries but takes no new builds.

If the worker crashes after launching a command but before saving its result, the attempt is reported as indeterminate. Toki does not re-run it automatically, because it cannot prove the first run had no side effects.

Keep the state directory

Keep the journal and result files together and retain them across upgrades. Deleting either removes the evidence Toki needs to recover.

Output ​

Output is returned when the command ends, including after cancellation or a deadline. Failed attempts keep their own stdout and stderr; retries never concatenate logs. More than 4 MiB of combined output is reported as a transport failure. Status lines on stderr contain only the component and its connection state.

Configuration reload ​

The running worker watches its configuration file, including atomic replacement. You can change the coordinator connection (endpoint, CA, server name, credential) without a restart:

  • the new connection is validated over TLS and protocol negotiation before switching;
  • an in-flight command finishes on its existing connection first, and the worker reports update-pending meanwhile;
  • a malformed file or unreachable endpoint keeps the working connection and reports configuration-rejected or update-unavailable; updates are retried.

The last working connection is kept in <config-name>.working.json beside the configuration, and is used for recovery after a restart. It also contains a credential.

Changing workDir, stateDir or builds needs a supervised restart.

Coordinator address changes ​

On the coordinator side, change addresses with one settings file:

json
{
  "coordinatorUrl": "https://builds.example:7444",
  "serverName": "builds.example",
  "listen": "0.0.0.0:7444"
}
sh
toki build configure --config /var/lib/toki/coordinator/server.json --settings address.json

listen is the local binding; coordinatorUrl is the advertised endpoint, and they may differ (for example behind a port forward). The running coordinator applies the change, renewing its certificate when the TLS name changes. The command prints a public {version, connection} publication with coordinatorUrl, serverName and caPem. Copy those fields into your client and worker files; their credentials stay the same.

Managed workers ​

Tama can manage the worker for you. In Tama's worker settings, enable Toki, choose the native release and enter the coordinator connection. Tama downloads the pinned executable, verifies its size and SHA-256, starts it and reports its connection state.

Disabling Toki or changing the settings cancels and reaps the current command before the worker is stopped or replaced. If Tama exits, including when it crashes, its managed worker stops too.

Daemon updates ​

The coordinator can be updated in place by a supervising owner:

sh
toki daemon-update manage --config update.json
toki daemon-update select --config update.json --desired desired.json

manage runs the coordinator as its child. select delivers a desired release: an uploaded executable pinned by its BLAKE3 digest, size, OS and architecture, under a monotonically increasing generation.

An update drains rather than kills. The running child stops dispatching new builds, keeps serving active workers until their results are durable, then exits; queued work stays in the database. The new executable starts with dispatch paused until it is healthy. A failed start restores the last healthy executable. To roll back, select the older release under a new generation.

WARNING

Run only one manager per coordinator configuration. In Tama-managed setups, Tama owns release publication and rollout policy; the production launcher is still being delivered.

Containment ​

Each command runs inside the strongest native boundary the platform offers.

Windows uses a Job Object. Commands start suspended until they are in the job, so all descendants inherit it. cpuRate is a hard CPU cap. memoryBytes is a committed-memory threshold: crossing it kills the whole job at the next poll. Accounting covers the entire job, including exited children.

Linux uses cgroup v2 when the worker's environment sets TOKI_CGROUP_ROOT to a private, operator-delegated subtree:

  1. Create a subtree for this worker installation only.
  2. Enable the cpu, memory and pids controllers in its cgroup.subtree_control.
  3. Start the worker with TOKI_CGROUP_ROOT pointing at it.

Toki creates one owned toki-action-* child per command. Memory uses memory.max with group OOM termination; task count uses pids.max. Cancellation writes cgroup.kill, which also catches processes that left the process group. After a crash, the next launch cleans up unlocked children. Toki never enables host controllers or changes privileges.

Without TOKI_CGROUP_ROOT, Linux uses process-group containment, which is explicitly incomplete, and any requested limit is refused before launch.

macOS tracks descendants by polling, kills them even after they leave the process group, and reports escapes. Polling can miss very fast fork sequences, so results always say trackingComplete: false. CPU and memory limits are refused, and a worker configured with memoryBytes or cpuRate fails at startup.

Not a security sandbox

None of these backends isolate the filesystem, network or secrets. Same-user code can escape resource containment. Use Toki for cooperative, trusted workloads.

Part of the Tama toolchain.