Code Interpreter
Deployment

Running without KVM

How to run on hosts with no /dev/kvm, and exactly what you give up by doing so.

The default stack boots the sandbox inside a libkrun microVM and maps /dev/kvm into the sandbox container. On hosts without a usable /dev/kvm, Docker fails to start that container outright.

Common cases: budget VPS instances, LXC containers, and nested virtualisation without KVM passthrough.

The override

Layer the no-KVM override onto the default file:

docker compose -f docker-compose.yaml -f docker-compose.nokvm.yml up

For the scalable stack, use its companion:

docker compose -f docker-compose.scalable.yml -f docker-compose.scalable.nokvm.yml up

On Kubernetes, set workerSandbox.kvmEnabled=false in the Helm values.

Either way the effective setting is KVM_ENABLED=false, which switches the sandbox runner from microVM mode to NsJail-only mode.

What you give up

This is a real reduction in the security boundary

NsJail-only mode shares the host kernel with untrusted code. It is appropriate for local development and for code you trust. It is not appropriate for executing untrusted code from people you don't trust.

Here is the concrete difference:

LayerMicroVM modeNsJail-only mode
Guest kernelSeparate kernel inside libkrunNone: host kernel is shared
NamespacesApplied, inside the guestApplied, on the host
seccomp-bpf filterAppliedApplied
cgroups v2 limitsAppliedApplied
rlimitsAppliedApplied
Non-root executionAppliedApplied
Empty network namespaceAppliedApplied
Blast radius of a kernel exploitA throwaway VMYour host

Everything except the kernel boundary is unchanged. That one row is the whole argument.

The sandbox still has no network access, still runs unprivileged, still has its syscalls filtered, and is still resource-capped. What changes is what a successful kernel-level exploit reaches: in microVM mode it lands inside a disposable guest; without KVM it lands on the machine running your infrastructure.

When NsJail-only is a reasonable choice

  • Local development on your own machine.
  • CI pipelines running code from your own repository.
  • Internal tooling where every caller is already trusted with host access.

When it is not

  • Any deployment where a language model generates the code.
  • Any deployment reachable by users you do not personally trust.
  • Anything multi-tenant.

If you need to run untrusted code and your host cannot do KVM, the answer is a host that can: not this override.

Checking which mode you are in

The sandbox runner logs its mode at startup. You can also confirm from the outside that the stack is up and which runtimes it has:

curl -s http://localhost:2000/api/v2/runtimes | jq

For the mode itself, inspect the container's environment:

docker compose exec sandbox-runner sh -c 'echo "KVM_ENABLED=$KVM_ENABLED"'

On this page