OpenWorker Service on a local machine
Run the API, controller, worker and PostgreSQL in Docker Compose. ows connects
through HTTPS and submits agents to an existing NVIDIA OpenShell gateway.
This reference is for local integration testing. It does not install Kubernetes
or OpenShell, and it is not a production HA deployment.
For the native ows deploy local Kubernetes installer, including pinned OpenShell
installation or reuse of an existing gateway, see the
local installation guide.
ows / application SDK
│ HTTPS + bearer token; REST requests and SSE events
▼
TLS ingress ── API ── PostgreSQL
▲
controller + worker
│ gateway mTLS
▼
NVIDIA OpenShell on Kubernetes
sandboxed ToolRunner
Only the HTTPS port is published, on host loopback. PostgreSQL uses TLS on a private Docker network. Gateway certificates are available to the controller and worker; the API has none. The controller creates/deletes environments. Model keys are mounted only into the worker. Runtime roles run as non-root users, without a Docker socket. A short-lived root installer populates dedicated credential volumes.
Prerequisites
- Docker with Compose v2, Node.js 20+, OpenSSL, and the repository's Rust toolchain for a host-native CLI.
- A working OpenShell gateway with client mTLS credentials, reachable from the containers, plus a pinned runner image available to its Kubernetes nodes.
- A matching Linux
openworkerrunner binary. It must match the executable in the runner image and the installed tool bundle; an arbitrary image is insufficient. See OpenShell setup.
On Docker Desktop, host.docker.internal reaches the host. With Linux Docker,
host-gateway is configured for execution roles, but a host listener bound only
to 127.0.0.1 is generally not reachable from a bridge container. Use a gateway
address reachable from Docker and retain certificate-name verification. Do not
expose an unauthenticated gateway or disable TLS verification to make it connect.
Build
From the repository root:
cargo build --manifest-path harness/Cargo.toml --locked --release -p openworker-service-cli
docker build --target runtime -f deploy/service/Dockerfile -t openworker-service:local .
The host CLI is harness/target/release/ows. The image includes Linux ows, the
service executable and the runtime. Base image digests and the Cargo lockfile are
pinned; system package downloads still use the distribution repository. Build on
the intended architecture. This milestone was qualified on ARM64, not x86-64.
For development with already-built Linux binaries, put ows,
openworker-server-reference and openworker in .ow-service-build/out/ and use
--target prebuilt. Never copy host macOS binaries into that directory.
The Docker build context excludes generated state and credentials.
Configure and start
Copy connection.example.json to a private local file.
Supply the gateway endpoint, TLS server name, certificate directory containing
ca.crt, tls.crt, tls.key, matching runner path, and image digest. The example
uses scripted: true: it exercises orchestration with deterministic model outputs
and real tools, without a model key.
For live model use, set scripted: false, modelProvider to openai or
anthropic, model to an available model ID, and modelKeyFile to a private file
containing only the key, not an environment assignment. The file is copied to
local private state and a worker-only volume. This installer does not yet configure
custom provider endpoints or hot credential rotation.
node deploy/service/stack.mjs init .ow-service /absolute/connection.json openworker-service:local
node deploy/service/stack.mjs up .ow-service
harness/target/release/ows --config .ow-service/cli.json whoami
Initialization creates a unique deployment/service ID, local CA, short-lived server
certificates, random PostgreSQL password and an admin bootstrap token with a
one-hour default lifetime. The token is
installed through a private one-time job, never an unauthenticated API call. Keep
.ow-service/ private and out of version control. The generated CLI context pins
the service identity and CA and stores a token-file reference, not the token.
Default URL: https://localhost:58443; pass another port as the last init argument.
up waits for containers and PostgreSQL, but the subsequent whoami is the
application-level readiness check. If startup fails, use status and inspect only
this deployment's container logs. The installer withholds captured subprocess
output when it might contain credentials. Do not paste state/config files into logs.
Deploy and submit an agent
See the CLI quickstart for profile and agent definitions, submission, approvals, questions and cancellation. Deployment publishes immutable JSON/YAML definitions selecting tools already installed in the image. It does not upload native code or arbitrary tool servers.
The default bundle contains read_file, write_file, and run_shell. In this
milestone the OpenShell workspace is /sandbox and the execution network policy is
network-deny. Approval bypass does not disable sandbox policy.
An opt-in coding runner and catalog adds bounded search/patch/Git and managed-process tools, with Node, Python, Git and curl in the development image. It does not change this minimal default. The local real-model exercise found remaining turn-budget, argument-error and cross-turn process-lifetime gaps; it is not yet a passing long-running coding acceptance.
End-to-end qualification
Against a scripted deployment and a real local OpenShell gateway:
node deploy/service/qualify.mjs .ow-service harness/target/release/ows
This submits real file operations, answers approvals/questions, rejects wrong TLS
trust and credentials, verifies idempotency conflicts, restarts API/worker, stops
and starts the full stack with retained volumes, cancels a task, closes the session
and deletes its sandbox. A passing run writes .ow-service/qualification.json.
It restarts this deployment: use a dedicated instance, not a shared working service.
A failed run retains evidence and resources for inspection; it does not blindly
retry uncertain tool actions or destroy the database.
Stop, resume, remove
node deploy/service/stack.mjs status .ow-service
node deploy/service/stack.mjs down .ow-service
node deploy/service/stack.mjs up .ow-service
down preserves database/credential volumes and remote environments. Image identity
is pinned at initialization; retagging a changed image cannot silently upgrade an
existing deployment. This milestone has no automated image-upgrade command.
Before destruction, cancel/finish runs, close sessions and explicitly delete each
environment using ows. Deletion is asynchronous: repeat with the same key to
observe it, or use environment get. The controller dispatches deletion once;
after connection loss it only checks the original object's state. A permanently
unknown outcome requires operator reconciliation, not a new delete request.
ows --config .ow-service/cli.json environment list
node deploy/service/stack.mjs destroy .ow-service THE_EXACT_PRINTED_DEPLOYMENT_ID
Destruction refuses while owned environments remain. It removes only this Compose project's containers/volumes; OpenShell and Kubernetes remain untouched. The local state directory and credentials remain for deliberate operator disposal. Once destruction starts, the deployment identity cannot be restarted against an empty database. An interrupted destruction can be resumed with the same exact ID.
Expiring service tokens, revisioned configuration and Kubernetes pool management are covered by the M4 guide. Hosted SSO follows later. Model connections/secrets and worker-slot settings currently remain deployment configuration.
Cloud installation uses the same native installer through ows deploy cluster.
See the experimental AWS lifecycle guide
for planning, guard checks, image publication, private Secret handoff and recovery.
The bounded Oregon/Linux ARM64 AWS artifact trial
also exercises actual Pod Identity/S3 transfers and scheduled cleanup. Its proxy
fix was qualified via a reviewed chart upgrade, rather than a fresh final-chart
AWS install. Other cloud configurations and final billing attribution remain open.
Optional durable artifacts use
/v1/sessions/:sid/artifacts with the same namespace/session authorization as the
rest of the service. Only content paths accept up to 64 MiB and disable proxy
request buffering; other requests retain the small JSON limit. Customer ingress
must preserve those bounds and streaming behavior. Tokens, AWS credentials and
artifact storage locations are never supplied in model output or coworker bundles.