Repository navigation
feat: native Linux compute driver (openshell-driver-oci) #2255
Description
Problem Statement
OpenShell's four compute drivers (openshell-driver-docker, openshell-driver-podman, openshell-driver-kubernetes, openshell-driver-vm) all translate OpenShell sandbox policy into a third party's API: a container engine daemon, a cluster control plane, or libkrun. Each translation seam is a place where semantics can drift from what OpenShell actually intends:
- Heuristic detection instead of deterministic behavior. Sandbox stuck in Provisioning on macOS with Podman (libkrun): docker driver resolves host-gateway to unreachable bridge IP #1519 (closed) shows the docker driver's
uses_host_gateway_alias()fingerprinting Docker Desktop, Colima, Lima, Rancher Desktop, and OrbStack by daemon OS string/hostname/labels, with no pattern for a Podman-backed Docker-compatible API on macOS —host.openshell.internalresolved to an unreachable bridge IP and sandboxes stuck inProvisioning. This is a structural cost, not a one-off bug: the "Docker-compatible API" is several different runtimes with divergent networking realities that need continual fingerprinting. - Host dependency for local/default use. Every local OpenShell run currently starts with "install Docker or Podman first." feat: support bubblewrap and Apptainer sandbox drivers for rootless/NFS hosts #1393 (open, HPC-focused) independently identifies this as a blocker in locked-down environments: enterprise policies that forbid new daemons, rootless Podman's NFS/
/etc/subuidfriction, and virtualization overhead where it isn't wanted. - Isolation enforcement is split across a translation boundary. The driver approximates policy through engine flags/pod specs/libkrun config, and the in-sandbox supervisor patches the rest at runtime. There is ongoing work (RFC 0012, in review) to make the supervisor's boundary-construction logic a pluggable
IsolationBackendcontract precisely because embedding it inline couples policy enforcement to whichever engine happens to be underneath, and blocks restricted/multi-tenant clusters that reject the elevated capabilities inline construction needs (feat: Support restricted SecurityContextConstraints for managed Kubernetes platforms #899).
Proposed Design
Add a fifth compute driver, openshell-driver-native, that constructs the sandbox from kernel primitives directly instead of delegating to an external engine. Scope, informed by what the codebase already has:
Isolation via the kernel, not a re-implementation of one. Use Linux namespaces (user, mount, PID, net, UTS, IPC, cgroup), cgroups v2 for the CPU/memory limits the gateway already accepts, and seccomp + no_new_privs. Generate an OCI runtime-spec config.json from policy and drive a bundled runc through the standard create/start/state/delete CLI contract — the same integration pattern containerd/CRI-O/Podman already use — rather than hand-rolling namespace/pivot_root orchestration or linking a runtime in-process (forking inside the gateway/driver's own multithreaded async process is a hazard regardless of which runtime is chosen, so every option here ends up out-of-process). runc was chosen over youki (Rust-native, faster per its own benchmarks, but far less production exposure and security review) because the isolation-critical path is the wrong place to prefer toolchain uniformity over the OCI reference implementation's much larger adversarial track record; the differentiated work here is mapping OpenShell policy directly onto primitives, not re-debugging a decade of container-runtime edge cases.
Isolation logic implemented as an IsolationBackend, not duplicated supervisor code. RFC 0012 explicitly anticipates a component implementing both the compute-driver and isolation-backend roles together (its "Extend the compute-driver contract" alternative calls this "natural for topologies such as MXC"). openshell-driver-native should be the Linux-native counterpart to that pattern rather than adding another one-off namespace-construction branch inside the supervisor — this is a hard dependency on RFC 0012 landing, not an optional nice-to-have. Doing anything else recreates exactly the coupling problem RFC 0012 was written to close.
Reuse the VM driver's OCI image and network machinery instead of rebuilding it. openshell-driver-vm already downloads registry layers into a valid OCI layout with a content-addressed cache under its state directory (crates/openshell-driver-vm/src/driver.rs), and already generates a per-sandbox nftables ruleset with NAT, default-deny forwarding, and an input chain scoped to the gateway port (crates/openshell-driver-vm/src/nft_ruleset.rs) — today gated behind the QEMU/GPU-passthrough path only. A native driver should extract the OCI-pull/cache logic into a shared crate and reuse it with overlayfs assembly in place of ext4 conversion, and generalize the existing nftables ruleset generator to a veth-based default path instead of writing either from scratch.
GPU via CDI directly. Apply CDI device nodes/mounts from the local CDI inventory when constructing the mount namespace, the same source Docker/Podman already read from — no translation layer needed.
Process model matching the existing driver pattern. ComputeDriver is a gRPC service (proto/compute_driver.proto), not an in-process trait; drivers are separate processes. Follow the openshell-driver-vm precedent exactly: gateway spawns the driver binary over a private Unix socket, passing its own PID so the driver can validate the peer (crates/openshell-server/src/compute/vm.rs).
Rootless by default. User namespaces with newuidmap, no root requirement, no long-running daemon.
Alternatives Considered
- feat: support bubblewrap and Apptainer sandbox drivers for rootless/NFS hosts #1393 (bubblewrap/Apptainer daemonless driver). Solves a related but distinct problem: unprivileged HPC hosts where installing any new tooling is restricted, using existing external unprivileged sandboxing tools rather than OpenShell owning the runtime. That approach trades control (thinner policy mapping, external tool's isolation semantics) for zero new binary footprint. This proposal is a different point on the same spectrum — full ownership of the primitives for the default local/single-node experience — and the two are complementary, not competing; a locked-down-HPC driver and a flagship native driver can both exist.
- Extend the Docker/Podman driver's heuristics further. Keeps the host dependency and only patches the current symptom (Sandbox stuck in Provisioning on macOS with Podman (libkrun): docker driver resolves host-gateway to unreachable bridge IP #1519-style detection gaps); the next unrecognized runtime reopens the same class of bug.
- Do nothing / rely on Docker or Podman indefinitely. Keeps the ecosystem debuggability (
docker ps,docker logs) and defers the engineering cost, at the price of a permanent host dependency and translated-not-constructed policy enforcement.
Non-goals
- Replacing the Docker, Podman, Kubernetes, or VM drivers. Kubernetes and container-engine drivers remain the right choice for existing infrastructure; this targets the local/default experience.
- Reimplementing an OCI runtime from scratch. This should bundle and drive an existing runtime (
runc) through its standard CLI contract. - Windows support — that is RFC 0013 (native Windows via MXC), which is pursuing the same "no in-sandbox supervisor binary" direction for a different kernel.
Agent Investigation
Grounded against origin/main:
uses_host_gateway_alias()—crates/openshell-driver-docker/src/lib.rs:2456-2486; no Podman pattern; feedsdocker_gateway_route_for_host(lib.rs:2420-2442) anddocker_extra_hosts(lib.rs:2488-2499).- VM driver OCI layout + content-addressed cache —
crates/openshell-driver-vm/src/driver.rs:4293-4353(layout writers),driver.rs:3623-3746(digest-verified blob download),driver.rs:4273-4390(cache root/keying), rooted underconfig.state_dir(driver.rs:440-446). - VM driver rootfs assembly — layers extracted via
extract_layer_blob_to_dir(driver.rs:3795) and converted to ext4 viacrates/openshell-driver-vm/src/rootfs.rs:83-129. - VM driver nftables ruleset (NAT + default-deny + gateway-port-only input) —
crates/openshell-driver-vm/src/nft_ruleset.rs:18-61— currently wired only throughsetup_tap_networking(crates/openshell-driver-vm/src/runtime.rs:402), called only from the QEMU/GPU path (runtime.rs:77-131); the default libkrun path uses agvproxysocket instead and does not install this ruleset (runtime.rs:654-813,crates/openshell-driver-vm/src/lifecycle.rs:109-111). - Gateway-spawns-driver-as-subprocess-with-peer-PID-validation pattern —
crates/openshell-server/src/compute/vm.rs:452-489; enforced viacrates/openshell-driver-vm/src/main.rs:269-271andmain.rs:426-448. ComputeDriveris tonic-generated fromproto/compute_driver.proto:18-43, not a hand-written Rust trait; concrete implementations are separate processes (e.g.crates/openshell-driver-podman/src/grpc.rs:32-152).- RFC 0012 (Isolation Backend interface, in review, PR rfc-0012: Isolation Backend interface #2048) and RFC 0013 (native Windows via MXC, in review, PR docs(rfc): add RFC 0013 native Windows support via MXC #2071) are the closest in-flight prior art; this proposal is designed to depend on and compose with RFC 0012 rather than duplicate its scope.
Activity
elezar commentedon Jul 14, 2026
This would be interesting. I would have the following quick questions:
runcinstead of allowing users to supply their own OCI-compliant low-level runtime?ericcurtin commentedon Jul 14, 2026
Agree we can make it configurable... It's just runc is by far the most deployed one docker, containerd, CRI-O, etc. Although crun that podman uses is great.
But bundling runc make installation a bit more seamless... We could do both maybe? Bundling and configurable?
Performance and scale... Usability I guess (things like GPU via CDI directly), because we can tailor specifically to OpenShell usecases... FWIW, I think this is probably a more pragmatic proposal than bubblewrap... The authors of bubblewrap have even moved away from it for new solutions, like @cgwalters @alexlarsson (just tagging them to keep me honest).
Maybe native is the wrong name, maybe it should be runc, etc.
Personally I wouldn't have interest in implementing if it wasn't a first class citizen, but maybe others would.
cgwalters commentedon Jul 14, 2026
On MacOS, it's just required to have a Linux VM which is an inherent part of this skew.
I have a very strong opinion related to this, see https://blog.verbum.org/2026/03/23/agent-security-is-just-security/ - which is an argument against OpenShell having its own agent-specific way to run containers.
I don't think having a new "native" driver would help here if we still need to support podman/docker - and I think we do for a very important reason - we should support a flow like
docker|podman build-> run with openshell, and if we have a different container storage, that becomes an impediment.ericcurtin commentedon Jul 14, 2026
I think @jmabry should look at this, with a few tweaks I think it can solve the issues in:
#1393
feat(driver-native): add containerd-backed native compute driver
jmabry commentedon Jul 16, 2026
Working off direct Linux primitives instead of
bwrapseems fine. From #1393, the ability to support NFS mounts, rootless configuration for running on HPC nodes are the most important requirements. Be aware many HPC environments stuck on Rocky 8 so development should be against these older OS's. @ericcurtinericcurtin commentedon Jul 16, 2026
Rocky 8 is useful information, can be done, that might need CI to ensure we stay compatible with older linux bases.
feat(driver-native): add containerd-backed native compute driver
feat(driver-oci): add containerd-backed OCI compute driver
[-]feat: native Linux compute driver (openshell-driver-native)[/-][+]feat: native Linux compute driver (openshell-driver-oci)[/+]refactor(driver-vm): extract shared nftables ruleset crate
feat(rootfs): add rootfs provider boundary with containerd-backed pro…
feat(driver-oci): add OCI compute driver on the rootfs provider boundary
refactor(driver-vm): extract shared nftables ruleset crate
feat(rootfs): add rootfs provider boundary with containerd-backed pro…
feat(driver-oci): add OCI compute driver on the rootfs provider boundary
elezar commentedon Jul 28, 2026
Following up on the discussion around #2312, I think this issue should be scoped as an extension-driver-first OCI/runc implementation.
Proposed direction:
CreateSandbox.openshell-driver-ocias a standaloneComputeDriverservice over a protected Unix socket.compute_driver.protofor v1; defer richer capability negotiation until the first implementation proves which fields are needed.Initial release acceptance criteria:
runclifecycleNon-goals for the first release:
github-actions commentedon Aug 28, 2026
This issue has had no activity for 14 days and is now marked stale. It may be closed in 7 days if there is no further activity. Comment or remove the state:stale label to keep it open.
github-actions commentedon Oct 13, 2026
Closing this issue after 14 days with no activity since it was marked stale. Reopen it if the work is still relevant.