Skip to content

Sandbox provider that can be self-hosted (and pin an image toolchain) #466

Description

@rycerzes

What problem are you trying to solve?

There is no sandbox provider that can be fully self-hosted.

daytona is the only one exposed in catalog/sandbox-catalog.yaml, and SandboxProviderManifestSchema is still a single variant carrying a TODO to widen it when a second provider ships. Daytona went closed source in June 2026 and the public repo is frozen, so a current instance cannot be deployed on your own infrastructure. LocalSandboxProvider is implemented and tested but unreachable from configuration, and it is a host-process sandbox rather than an image-based one, so it cannot pin a toolchain.

My use case is an agent that compiles and benchmarks CUDA inside the sandbox primitive — a performance number measured somewhere other than where the kernel runs is not a measurement. That needs a reproducible image with a specific CUDA toolchain, and a GPU, and a container is currently the only sandbox that can provide either.

Proposed solution

A container-backed sandbox provider implementing the existing SandboxProvider interface, with an optional gpus field passed through to --gpus.

LocalSandboxProvider is the natural reference to port from: same interface, same path-shaped sandboxId, same file-transfer and traversal concerns, with docker exec replacing the bwrap supervisor. The shared sandboxProviderContractSuite already has a branch for path-id backends, so correctness is measured against your tests rather than new ones.

Alternatives considered

Extending LocalSandboxProvider instead. Worth saying clearly, because it is easy to assume otherwise: bubblewrap can reach a GPU. A CUDA kernel runs under bwrap in an unprivileged user namespace at 920.1 GB/s against 920.7 GB/s on the host — the namespace is genuinely new (/proc/self/ns/user differs) and genuinely unprivileged (uid_map is 1000 1000 1).

Probing cuInit through dlopen("libcuda.so.1"):

bwrap configuration cuInit
nvidia nodes --dev-bind, no /sys CUDA_ERROR_OPERATING_SYSTEM (304)
--ro-bind /dev + /sys CUDA_ERROR_NO_DEVICE (100)
--dev-bind /dev + /sys OK, devices=1
--ro-bind /dev, nvidia nodes --dev-bind, + /sys OK, devices=1

Two requirements: /sys must be mounted, and the nvidia device nodes must be writable. /dev itself can stay read-only.

That said, LocalSandboxProvider cannot be given a GPU through its configuration, and the reason is one level down in @anthropic-ai/sandbox-runtime rather than in TrueForge.

Driving hostRun's createSandbox + runSupervisorSession directly, with the shipped ALLOW_READ_BY_PLATFORM.linux policy:

probe inside the sandbox result
/sys present yes
ls /dev/nvidia* No such file or directory
/dev contents core fd full null ptmx pts random shm stderr stdin stdout tty urandom zero
/dev mount a fresh tmpfs, over the host devtmpfs
test -w /dev/nvidiactl no
nvidia-smi couldn't communicate with the NVIDIA driver

So /sys is already satisfied, but the device nodes are not read-only — they are absent. Listing /dev in allowRead does not surface them, because SRT mounts its own minimal /dev and drops /dev/* entries from the allowlist on purpose (dist/sandbox/linux-sandbox-utils.js):

// Skip /dev/* paths since --dev /dev already handles them
if (normalizedPath.startsWith('/dev/')) {

I could not find a device-passthrough option in SRT's config surface. So getting a GPU into the local provider is not a policy change you can make in this repo — it needs SRT to grow a device allowlist first. Happy to be wrong about that if there is a surface I have missed.

That is orthogonal to self-hosting anyway, which is the part I actually need.

Additional context

Related: #387 (E2B, help wanted) and #414 (ComputeSDK, closed) are both asking for non-Daytona backends.

I have a working implementation — ~810 lines plus contract, GPU and hardening tests — passing sandboxProviderContractSuite (4/4) and leaving the default packages/trueforge unit suite untouched. It streams file transfer through docker cp/stdin rather than base64-into-argv, so it does not reproduce #416.

Raising this as an issue first per the approval note in CONTRIBUTING.md. Happy to open the PR if you want to see it, to rework it if the shape is wrong, or to leave this as analysis if a container provider is not a direction you want to take.

Environment: Linux, Node 22.14, Docker 29.7.2 with the NVIDIA runtime, RTX 4090 (sm_89), driver 580.159.04, CUDA 13.2.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions