Cloudflare Containers
Run each task's workspace in a Cloudflare Container through a bridge Worker you deploy, with model keys and tracker tokens kept on your own host.
With sandbox.provider: cloudflare, each task's workspace runs in a Cloudflare Container instead of on your Mac or server. SI Fabrik drives it through a bridge Worker you deploy from the SI Fabrik source (cloudflare/bridge). It behaves like the Docker sandbox, and as there, model keys and tracker tokens never enter it: they stay on your own host. The read-only rules for GitHub and package registries apply to Docker sandboxes only.
How it keeps secrets and networks private#
- No internet by default. Each sandbox starts with internet access off. Only HTTP and HTTPS can leave it, and every request passes the bridge's egress check, which applies the same allowlist rules as Docker sandboxes: the host-wide defaults plus
sandbox.network.allow. - Model keys stay on your host. Model and tracker-tool traffic goes to
198.18.0.1, an unroutable address inside the sandbox. The bridge relays it over SI Fabrik's own outbound WebSocket, and SI Fabrik swaps the placeholder key for the real one. Private services, such as a LiteLLM proxy on your VPN or a private tracker, are reached from your host and never need exposing. - Code moves as git bundles. SI Fabrik checks every object it imports (
fetch.fsckObjects). The sandbox needs no access to your git host. - One token. Only SI Fabrik talks to the bridge, with
Authorization: Bearer <HARNESS_BRIDGE_TOKEN>. Browser origins are refused.
Deploy the bridge#
You need a Cloudflare account on the Workers Paid plan (Containers require it), Node 20 or later, Docker to build the images, and crane (brew install crane) to push them.
- Log in and create a tokenShell
cd cloudflare/bridge npm install npx wrangler login openssl rand -hex 32 # the bridge token npx wrangler secret put HARNESS_BRIDGE_TOKEN - DeployShell
../../scripts/deploy-bridge.shThe script builds the
sandboxandbrowser(Chromium plus Playwright) images forlinux/amd64, tags each by its content so an unchanged image is never uploaded again, pushes them to Cloudflare's registry with crane, checks they really are amd64, and deploys the Worker with each image pinned by digest.--worker-onlyredeploys a Worker change with the images from the last deploy (a few seconds).--dry-runbuilds and shows what would change, and changes nothing.
Plain
npx wrangler deployalso works, but it pushes every image through the Docker daemon. Docker Desktop's built-in proxy can drop large layers on slow or VPN links; the browser image is about 1 GB. - Connect SI Fabrik
Open Settings → Sandbox → Cloudflare sandboxes. Enter the Bridge URL (
https://harness-sandbox-bridge.<account>.workers.dev) and the Bridge token (HARNESS_BRIDGE_TOKEN). It's saved asHARNESS_CLOUDFLARE_TOKEN. Press Test Connection: SI Fabrik starts a throwaway sandbox with no network, runs a command and destroys it.harnessd.yamlsandbox: cloudflare: bridge_url: https://harness-sandbox-bridge.your-account.workers.devsecrets.envHARNESS_CLOUDFLARE_TOKEN=… # the bridge's HARNESS_BRIDGE_TOKEN; host-only, never passed to agentsOr set both from the app in Server Settings → Sandbox. The test runs from the server with its saved token.
- Use it in a projectWORKFLOW.md
sandbox: provider: cloudflareOr choose Cloudflare under Workflow → Settings → Sandbox → Run agents in.
Working with Cloudflare workspaces#
- The workspace lives in Cloudflare. Its task branch is saved back into your repository, but there's no local copy to reveal or open in an editor, so those actions are hidden. Use the terminal, the preview and the browser instead.
- Each task keeps a sandbox while it's active. Idle containers stop after 30 minutes; the next attempt rebuilds the workspace from the saved branch.
- Hooks run inside the sandbox, in
/workspace. - The browser and previews work as with Docker. Previews are proxied through the bridge to
http://127.0.0.1:79xxon your Mac. - The terminal opens in the sandbox. Inspect works on a throwaway copy of the workspace.
- Source links are mounted at
~/deps/<project>.
Running a linked project's app next to the agent (a project: service) isn't supported on Cloudflare. Use a hosted url: service.
The Cloudflare card#
On Sandboxes, the Cloudflare card shows:
- Bridge: its URL, whether a token is set, and whether it's healthy (checked every 15 seconds).
- Relay: whether SI Fabrik's relay WebSocket is connected, active routes and relayed requests.
- Running in Cloudflare: agents running there, with a terminal and a stop button each.
- Workspaces in Cloudflare: kept workspaces. Save branch and destroy saves the task branch into the project repository first, then removes the sandbox and its container.
Bridge API#
For reference, the bridge Worker serves:
| Route | |
|---|---|
GET /health | No auth |
POST /v1/sandboxes/:name {allow, hub, image} | Start the sandbox or update its policy. image is sandbox (default) or browser. Returns {running, fresh} |
GET /v1/sandboxes/:name/exec (WebSocket) | First frame {argv, cwd, env}, then stdin; output frames prefixed 1 (stdout) or 2 (stderr), then {type:"exit", code} |
ANY /v1/sandboxes/:name/port/:port/* | Proxy to an app in the sandbox (previews); token in X-Harness-Authorization |
GET /v1/sandboxes/:name/denied | Hosts the policy refused since the last call |
DELETE /v1/sandboxes/:name | Destroy the sandbox |
GET /v1/relay?hub=:id (WebSocket) | SI Fabrik's relay connection |
Develop the bridge locally#
printf 'HARNESS_BRIDGE_TOKEN=%s\n' "$(openssl rand -hex 32)" > .dev.vars
npx wrangler dev --port 8797Point SI Fabrik at http://127.0.0.1:8797; plain http:// is only accepted for localhost. Local dev emulates Cloudflare's network with a transparent proxy, so raw TCP connections appear to connect but carry no data. In production only ports 80 and 443 leave the container.