Cloudflare Provider
Use provider: cloudflare or provider: cf to run Linux commands through a Cloudflare Worker backed by Cloudflare Containers. This is a delegated run provider: the local CLI builds the repo archive, owns local lease claims, renders commands, and streams timing output; the Worker runner creates the container, uploads files, executes commands, and tears the container down.
Cloudflare Containers run behind container-enabled Durable Objects. That makes the provider a good fit for short Linux test jobs and warm repeated commands, but not for SSH-oriented workflows.
#Requirements
- Cloudflare Workers Paid account with Durable Objects and Containers enabled.
- Wrangler authenticated for the target account.
- Docker or a Docker-compatible daemon available to Wrangler for image builds.
- Deployed Crabbox runner from
worker/wrangler.cloudflare.jsonc. - Worker secret
CRABBOX_RUNNER_TOKEN. - CLI-side
CRABBOX_CLOUDFLARE_RUNNER_URLand
CRABBOX_CLOUDFLARE_RUNNER_TOKEN.
The Worker entrypoint is worker/src/cloudflare-container-runner.ts. The container image is built from worker/cloudflare-container.Dockerfile and runs the Go HTTP runner in worker/cloudflare-container-runner.
#Configuration
Repo config should select the runner and remote workdir only:
provider: cloudflare
cloudflare:
apiUrl: https://crabbox-cloudflare-container-runner.example.workers.dev
workdir: /workspace/crabbox
Keep the bearer token in a shell secret, credential manager, or user-level config. Do not commit it to repo YAML.
export CRABBOX_CLOUDFLARE_RUNNER_URL=https://runner.example.workers.dev
export CRABBOX_CLOUDFLARE_RUNNER_TOKEN=...
--cloudflare-url can override the runner URL for one command. The runner token is intentionally not exposed as a command-line flag because command-line arguments can be captured in shell history and process listings.
Check the configured runner URL and token without creating a container:
crabbox doctor --provider cloudflare
#Deploy
Install dependencies and verify the Worker before deploy:
npm ci --prefix worker
npm run check --prefix worker
npm run build:cloudflare --prefix worker
Set the runner bearer token as a Worker secret:
printf '%s' "$CRABBOX_CLOUDFLARE_RUNNER_TOKEN" \
| npx wrangler secret put CRABBOX_RUNNER_TOKEN \
--config worker/wrangler.cloudflare.jsonc
Deploy the Worker and container image:
npm run deploy:cloudflare --prefix worker
For a repeatable local gate, deploy, and live smoke, use:
scripts/deploy-cloudflare-smoke.sh
It expects CLOUDFLARE_ACCOUNT_ID, CLOUDFLARE_API_TOKEN, CRABBOX_CLOUDFLARE_RUNNER_TOKEN, and CRABBOX_CLOUDFLARE_RUNNER_URL in the environment. Set CRABBOX_CLOUDFLARE_SKIP_DEPLOY=1 to run only the local checks and live smoke, or CRABBOX_CLOUDFLARE_SKIP_SMOKE=1 to stop after deploy.
The deploy script passes --containers-rollout=immediate so Worker and container changes roll out together. If you call Wrangler directly, include that flag:
npx wrangler deploy \
--config worker/wrangler.cloudflare.jsonc \
--containers-rollout=immediate
Check the deployed container app:
npx wrangler containers list --config worker/wrangler.cloudflare.jsonc
npx wrangler containers info <container-application-id> \
--config worker/wrangler.cloudflare.jsonc
#Capacity
worker/wrangler.cloudflare.jsonc defines one Durable Object class per predefined Cloudflare instance type. Crabbox maps all generic classes to standard-4 because the smaller Cloudflare tiers are much smaller than the default Linux classes on other providers.
--class standard standard-4
--class fast standard-4
--class large standard-4
--class beast standard-4
Use --type lite|basic|standard-1|standard-2|standard-3|standard-4 for smaller smoke tests or quota control. Change max_instances in worker/wrangler.cloudflare.jsonc when the account should allow more or fewer concurrent containers.
lite is intended for no-sync and quick command smoke tests. Use basic or a standard-* type for archive sync, and prefer standard-* for dependency-heavy builds or tests. Large module downloads can exhaust the smaller container disks before the command itself starts.
Cloudflare's current predefined instance types range from lite to standard-4; standard-4 is 4 vCPU, 12 GiB memory, and 20 GB disk. See Cloudflare's Containers limits docs for current instance and account limits: https://developers.cloudflare.com/containers/platform-details/limits/
#Live Smoke
With the runner URL and token configured, first test the deployed runner without uploading the checkout:
crabbox run \
--provider cloudflare \
--no-sync \
--timing-json \
--shell \
-- 'df -h / /tmp /workspace; printf "npm cache=%s\n" "${NPM_CONFIG_CACHE:-}"; printf "pnpm store="; pnpm config get store-dir'
That one-shot run cleans up automatically. Use --keep when you want to inspect or reuse the same container:
crabbox run \
--provider cloudflare \
--keep \
--no-sync \
--shell \
-- 'uname -a; command -v go node pnpm gh'
crabbox stop --provider cloudflare <lease-id-or-slug>
Then run a sync smoke from a checkout:
crabbox run \
--provider cloudflare \
--type basic \
--timing-json \
--shell \
-- 'test -f go.mod && rg -n "stopped_with_code" internal/providers/cloudflare'
#Behavior
runcreates or reuses a container Durable Object, preparesworkdir,- Before upload, the provider checks remote disk headroom for both the archive
warmupstarts a container and leaves it alive untilcrabbox stopor thestatusandstopresolve local Crabbox claims, then call the runner.listreports local Cloudflare claims. Add--refreshto check runner state- The default image includes Git, GitHub CLI,
jq,ripgrep, Go, Node, and - npm and pnpm caches live under
/var/cache/crabbox, and the container - The runner stores lease metadata in Durable Object storage and schedules
crabbox cleanup --provider cloudflareonly checks local claims. It removes
uploads a gzipped archive of the local checkout unless --no-sync is set, extracts it, then relays stdout, stderr, and exit status.
and extracted checkout and fails early with a sizing hint if the selected type is too small.
configured TTL/idle deadline expires.
for those claims. The runner intentionally does not expose a global container enumeration API.
pnpm; repo-specific dependencies still belong to the repo setup command.
filesystem persists while the lease is active.
cleanup at the earlier of --ttl or --idle-timeout. Uploads and command execution extend the idle deadline.
claims whose runner state is expired, stopped, or missing.
Cloudflare Containers can also access Worker bindings through outbound handlers; Crabbox does not wire those by default, but custom runner images can add them: https://developers.cloudflare.com/containers/platform-details/workers-connections/
#Limitations
- Linux delegated
run,warmup,status,stop,list,doctor, and - SSH, VNC, browser desktop, code-server, Actions hydration,
--download, and --checksumis not supported because sync uses archive upload/extract rather- Cleanup cannot discover containers that do not have a local Crabbox claim.
- Container capacity is bounded by the checked-in Wrangler bindings and the
local-claim cleanup are supported.
--fresh-pr are not supported.
than rsync.
target account's Cloudflare Containers limits.