Read when:
- choosing
provider: opensandbox; - configuring OpenSandbox image, sizing, workdir, API URL, or proxy behavior;
- changing
internal/providers/opensandbox.
OpenSandbox is a delegated run provider. Crabbox uses the OpenSandbox Go SDK behind a provider-local client for sandbox lifecycle, file upload, and execd command execution. OpenSandbox owns the container runtime and command transport; Crabbox owns local config, repo claims, sync manifests and guardrails, slugs, timing summaries, and normalized list/status rendering.
The API key travels only in request headers. Forwarded command environment and archive content travel in request bodies, so Crabbox does not place secrets on process command lines.
Use OpenSandbox when the run should execute in an OpenSandbox-managed Linux
container and an SSH lease is not required. Use AWS, Hetzner, Static SSH,
Daytona, or another SSH-lease provider when the workflow needs crabbox ssh,
VNC, code-server, Actions runner hydration, or provider-native SSH access.
An OpenSandbox API endpoint and API key. Prefer loading the key from a secret manager or prompting into the environment so it never appears in shell history or process arguments:
export CRABBOX_OPENSANDBOX_API_KEY="$(
python3 -c 'import getpass; print(getpass.getpass("OpenSandbox API key: "))'
)"OPEN_SANDBOX_API_KEY is accepted as an environment fallback.
Set the API URL explicitly from a trusted local environment or CLI flag. For a local-development OpenSandbox server, use the SDK endpoint directly:
export CRABBOX_OPENSANDBOX_API_URL=http://localhost:8080For hosted or shared deployments, set the HTTPS origin for that deployment.
crabbox warmup --provider opensandbox
crabbox run --provider opensandbox -- go test ./...
crabbox run --provider opensandbox --id blue-lobster --shell 'pnpm install && pnpm test'
crabbox status --provider opensandbox --id blue-lobster
crabbox stop --provider opensandbox blue-lobster
crabbox cleanup --provider opensandboxCrabbox resolves the API key from, in order,
CRABBOX_OPENSANDBOX_API_KEY, then OPEN_SANDBOX_API_KEY. It is sent through
the OpenSandbox SDK lifecycle and execd clients, never persisted in Crabbox
config and never placed on argv. If no key is resolvable, operations fail with
a clear error before any sandbox is created.
The API base URL can come from --opensandbox-api-url,
CRABBOX_OPENSANDBOX_API_URL, or OPEN_SANDBOX_API_URL. Repository YAML cannot
set the API URL. That prevents a checked-in config from redirecting an
automatically loaded API key. Overrides must be absolute HTTP(S) URLs; plain
HTTP is accepted only for localhost or loopback IPs during local development.
Userinfo, query parameters, and fragments are rejected.
Resolved execd endpoints follow the same transport rule: public endpoints must
use HTTPS, while plain HTTP is accepted only for loopback development servers.
Local lease claims are scoped to the normalized API URL and a random ownership marker stored both locally and in OpenSandbox sandbox metadata. Before reusing or deleting a retained sandbox, Crabbox verifies that both markers match. This prevents a local claim from being applied to a sandbox at another endpoint or account.
provider: opensandbox
target: linux
openSandbox:
image: ubuntu:24.04 # container image used for new sandboxes
workdir: /workspace/crabbox # sync target and exec cwd
cpu: "1" # resource limit string; empty = service default
memory: 2Gi # resource limit string; empty = service default
timeoutSecs: 0 # 0 = Crabbox TTL; positive values add a provider cap
execTimeoutSecs: 600 # command/sync-helper timeout
platformOS: linux # set with platformArch; both empty = service default
platformArch: amd64 # set with platformOS; both empty = service default
secureAccess: false # request secured endpoints
useServerProxy: false # route execd through the OpenSandbox serverProvider flags:
--opensandbox-api-url
--opensandbox-image
--opensandbox-workdir
--opensandbox-cpu
--opensandbox-memory
--opensandbox-timeout-secs
--opensandbox-exec-timeout-secs
--opensandbox-platform-os
--opensandbox-platform-arch
--opensandbox-secure-access
--opensandbox-use-server-proxy
--opensandbox-forget-missing
Configuration flags have matching CRABBOX_OPENSANDBOX_* environment
overrides, for example CRABBOX_OPENSANDBOX_IMAGE,
CRABBOX_OPENSANDBOX_WORKDIR, and
CRABBOX_OPENSANDBOX_EXEC_TIMEOUT_SECS. The API URL also reads
OPEN_SANDBOX_API_URL. --opensandbox-forget-missing is deliberately
CLI-only so stale-claim removal always requires explicit intent.
--allow-env and --env-from-profile are supported. Forwarded values are sent
in the OpenSandbox execd request body (envs), never on the command line:
crabbox run --provider opensandbox --allow-env API_TOKEN -- printenv API_TOKENwarmuporrunwithout--idcreates a sandbox with the configured image, resource limits, timeout, platform, secure-access setting, and Crabbox metadata (crabbox=true,crabbox.name=...,crabbox.claim=...).- The local lease is stored as
osbx_<sandbox-id>with a friendly slug and a repo claim. The sandbox expiration is the earliest configured provider timeout or Crabbox TTL. Crabbox never renews that absolute deadline; idle timeout remains the sliding local inactivity policy. - By default
runarchive-syncs the working tree: agit ls-files-driven manifest is packed into a gzipped tar locally, uploaded through the OpenSandbox file API, and extracted into the configured workdir.--no-syncskips the archive step and only ensures the workdir exists.--sync-onlysyncs and stops without running a command. - The command runs through OpenSandbox execd with
cwdset to the workdir andenvscarrying forwarded environment values. The remote exit code is mirrored by Crabbox. - On release the sandbox is deleted unless
--keepwas set.--keep-on-failureretains a newly created sandbox after a sync, workspace setup, or command failure and prints rerun/stop guidance. Best-effort cleanup calls are bounded; failed cleanup reports the sandbox ID for manual provider-side cleanup. cleanupremoves retained sandboxes after their local sliding idle timeout. Cleanup rechecks ownership metadata and serializes with lease reuse. Missing-or-inaccessible claims are preserved unlessforgetMissingis explicitly enabled.
- SSH: not driven by Crabbox.
- Crabbox sync: yes, via gzipped archive upload and in-sandbox extraction.
- Env forwarding: yes, off-argv in the exec request body.
- Provider sync: no separate provider-side copy command is required.
- URL bridge: no Crabbox bridge integration in v1.
- Desktop / browser / code: no Crabbox VNC or code-server surface.
- Actions hydration: no.
- Coordinator: no. OpenSandbox runs directly through its API and never through the Crabbox broker.
opensandboxhas no aliases in v1.osbis intentionally reserved so it cannot collide with the OpenSandbox CLI or a future maintainer choice.--checksumis rejected by core delegated-run guardrails because OpenSandbox does not expose Crabbox rsync checksum semantics.--sync-onlyand--force-sync-largeare supported.--no-synconly ensures the workdir exists. It never appliessync.delete, so reusing a retained sandbox does not erase its workspace.- With
sync.delete, Crabbox uploads and extracts into a sibling staging directory, then replaces the workdir only after extraction succeeds. crabbox liststarts from local OpenSandbox claims and fetches remote status for each retained sandbox. A missing sandbox remains visible asmissing-or-inaccessibleuntil explicitly forgotten.- For an existing lease, a 404 is account-ambiguous and keeps the claim by
default. Pass
--opensandbox-forget-missingtostoponly after confirming the sandbox is gone in the intended account. warmup --actions-runneris rejected because OpenSandbox is a delegated execution provider, not an SSH runner host.- Large-sync guardrails still apply; pass
--force-sync-largewhen a large archive sync is intentional. openSandbox.workdirmust be an absolute path and cannot be a broad system directory such as/,/tmp, or/workspace.
The opt-in live smoke script checks prerequisites, builds the local CLI, creates
a short-lived sandbox, proves archive sync and off-argv environment forwarding,
reuses the retained sandbox with staged sync.delete replacement, checks
list/status, and stops it:
CRABBOX_OPENSANDBOX_API_KEY=... \
CRABBOX_OPENSANDBOX_API_URL=... \
scripts/live-opensandbox-smoke.shIt prints exactly one classification:
live_opensandbox_smoke_passedenvironment_blockedquota_blockeddiagnostic_only
Related docs: