openblox¶
Self-hosted sandboxes for running untrusted, AI-generated code under gVisor by default.
openblox is a small Go library over Docker and gVisor, the default runtime; a microVM runtime such as Kata, a stronger boundary at a higher cost per sandbox, can be selected instead. There is no control plane, no database, and no scheduler — a sandbox is a container, and the container is the state.
backend, err := docker.New()
if err != nil {
return err
}
defer backend.Close()
// No options: no network, non-root, read-only rootfs, capped CPU/memory/PIDs,
// gVisor runtime, reaped when idle.
sb, err := backend.Create(ctx, "session-1",
sandbox.WithImage("ghcr.io/blox-eng/openblox-sandbox:latest"))
if err != nil {
return err
}
res, err := sb.Exec(ctx, sandbox.Command{
Argv: []string{"python3", "-c", "print(6 * 7)"},
})
fmt.Println(string(res.Stdout)) // 42
Status: pre-release
The API is taking shape and will change.
Why¶
Running code an LLM wrote, against files a user uploaded, is a hostile workload wearing a friendly hat. The usual answers are a hosted sandbox platform — which means your customers' data crosses someone else's boundary — or a plain container, which shares a kernel with the host.
openblox takes the third option: a substrate small enough to read in an afternoon, that you run yourself, with isolation supplied by gVisor (or a microVM runtime you choose) rather than by hope.
Where this sits¶
openblox is the layer below a sandbox platform, not a smaller one.
your scheduler, your tenancy, your API ← yours to build, if you ever need it
──────────────────────────────────────
openblox ← isolation, done correctly
──────────────────────────────────────
Docker + gVisor ← the boundary itself
The rule
How a sandbox is isolated is openblox's problem. Which sandbox runs where is yours.
Egress, capabilities, filesystem, resource caps, lifetime, runtime: openblox's. Placement, queueing, tenancy, metering, snapshots: not openblox's, and not planned. Build those on top when something actually asks for them. That is what a lower layer is for, and it is why there is no control plane to adopt first.
The comparison is libvirt, not OpenStack.
What you get¶
What it is not¶
- Not multi-tenant infrastructure. There is no scheduler and no multi-node story. One host, many sandboxes.
- Not a snapshot/fork/resume engine. Stop and re-create from a baked image.
- Not a substitute for a threat model. Read the security model and decide whether its guarantees match your workload.
The first two are the rule above, applied: they are placement, not isolation. They are not gaps waiting to be filled.
Measuring it¶
The claims in the security model are backed by tests, not assertion. The
adversarial suite that exercises them — network, filesystem, privilege,
process, timeout and lifecycle attacks — is pkg/conformance, a package
written against the sandbox.Backend interface rather than against
pkg/docker alone. Any implementation of that interface can be run against
it and measured the same way. It has only ever run against pkg/docker: under gVisor
on every pull request, and under Kata on amd64 in a separate workflow that does not
gate merges.
Next¶
- Quick start — install, prerequisites, a working example
- Production —
openbloxd, compatibility, upgrades, troubleshooting - Security model — what is isolated, how, and what is not claimed
- The image contract — what an image must provide
A question that is not an issue belongs on Discord.