kern: A fast, rootless sandbox and virtual resource runtime for any workload, including untrusted and AI-generated code.
A real, kernel-enforced container in 3.4 ms, out of one 1.83 MB binary with no daemon.
0 RAM at rest · no daemon, no socket, nothing to start · one static binary, libc its only Rust dependency
# Linux and ARM boards. Windows (WSL2) and building from source are just below.
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | sh
kern box dev --image alpine -it -- shkern runs Linux workloads in real, kernel-enforced sandboxes: user, PID, mount, network, UTS and IPC namespaces, an overlay or read-only root pivoted in, an always-on seccomp filter, and cgroup v2 limits. It pulls OCI images, builds them, runs them, and gets out of the way. No background daemon, one short-lived process per box.
The binary is 1.83 MB because it carries only what it has to. The entire Rust dependency tree is
libc, JSON and the OCI manifests are parsed by hand, and pull uses the curl and tar already
on the machine instead of linking a TLS stack and a decompressor. Those two are therefore a real
requirement of the image path, and kern doctor checks for them; a box from a --rootfs needs
neither.
It has two verbs. kern box wraps a process in a full isolated slice. kern run caps a resource
on a process you launch yourself, with no sandbox. Isolation is simply the first resource kern
manages; the same model slices CPU (vcpu:), memory, disk (vdisk:) and devices (vgpio:) per
process, defined once in a kern.toml and attached by name. See
docs/RESOURCES.md.
- Not a hypervisor. The boundary is the Linux kernel: namespaces, capabilities, seccomp and cgroups. A kernel privilege-escalation bug is an escape. For actively hostile, multi-tenant code from strangers, reach for a microVM (Firecracker, Kata) or gVisor. kern's ground is your own or semi-trusted code: CI jobs, build steps, dev sandboxes, an agent's tool-calls under your supervision.
- Not free of the userns trade. kern's isolation is built on an unprivileged user namespace, and userns has been a fertile source of kernel LPE bugs. Running untrusted code in a box hands it that surface to probe. SECURITY.md states this first, before any claim.
- Not a Docker Engine reimplementation. kern speaks Docker's formats, images and
docker-compose.ymland Dockerfiles, not its API. No overlay networks, no plugin ecosystem, no Swarm. Full matrix: docs/DOCKER-COMPAT.md. - Not a Kubernetes runtime. It does not implement CRI. For that, use containerd or CRI-O.
- Not shipping GPU slices. They are on the roadmap and there is no GPU code in this edition, so there is nothing here to trust or to attack yet.
What it does not know or does not do yet is written down in OPEN_ITEMS.md rather than left for you to find: an unattributed gap in a startup measurement, why the seccomp filter is still a denylist, which fleet limit is a guard rail instead of a boundary.
🐧 Linux and ARM boards (Raspberry Pi · Jetson · Arduino UNO Q). One line; auto-detects x86-64 / aarch64:
curl -fsSL https://raw.githubusercontent.com/getkern/kern/main/install.sh | shServed from github.com (read the script first if you like). It downloads the release binary for
your arch and verifies the sha256 before installing. No Rust toolchain required.
(getkern.dev/install.sh is a short alias.)
🪟 Windows. One line in PowerShell (no Docker Desktop, no Ubuntu):
irm https://raw.githubusercontent.com/getkern/kern/main/install.ps1 | iexFrom source, if you would rather build it yourself or want a target we do not publish a binary for:
cargo install --git https://github.com/getkern/kern getkern --lockedNeeds a Linux kernel with unprivileged user namespaces and cgroup v2. kern doctor tells you
whether boxes will run here before you try. Boards, WSL2, checksums and the long form:
docs/INSTALL.md.
kern box dev --image alpine -it -- sh # a throwaway shell in a real OCI image
kern run --memory 256M --cpus 0.5 -- ./crunch # cap a process, no sandbox
kern box svc --image nginx:alpine -d -p 8080:80 \ # a service: published, restarted, health-checked
--restart --health-cmd 'wget -qO- localhost:80' -- nginx -g 'daemon off;'
kern ps # what is running, with PORTS and HEALTH
kern exec svc -it -- sh # shell into it
kern top # live TUI: boxes, CPU/RAM, profiles, volumes
kern compose stack.toml up # a multi-box stack, kern TOML or compose.ymlUntrusted code, with the defaults doing the work:
kern box job --image python:3.12-slim --read-only --cap-drop ALL --memory 256m \
-v ./job:/w -- python3 /w/x.pyNo network unless you ask, a read-only root, dangerous capabilities dropped, seccomp always on. Ninety runnable examples, each doing one thing: examples/.
| kern | Docker | Podman | |
|---|---|---|---|
| Daemon | no | yes (dockerd + containerd) |
no |
| Rootless | yes, always | opt-in | yes |
| Cold start, bare box | 2.1 ms | ~294 ms | ~281 ms |
| Cold start, from an OCI image | 3.4 ms | ~294 ms | ~281 ms |
| Resident memory, nothing running | 0 | 154 to 160 MB | 0 |
| Footprint | one 1.83 MB binary | daemon stack | multi-binary install |
| OCI images, pull / build / push | yes | yes | yes |
docker-compose.yml |
yes, read as-is | yes | partial |
| Overlay networks, Swarm, CRI | no | yes | partial |
| GPU | on the roadmap | yes | yes |
Measured 2026-08-01 on an Intel i7-14700KF, Linux 7.0.0, against the runtimes installed there. Every
number below comes from one script you can run yourself, python3 examples/benchmark.py.
| kern | bubblewrap | runc | podman | docker | |
|---|---|---|---|---|---|
| Cold start (bare box) | 2.2 ms | 3.0 ms | 13.2 ms | 281.5 ms | 294.4 ms |
| 200 boxes in parallel | 0.09 s | 0.19 s | 0.30 s | 41.8 s | 16.6 s |
A thousand simultaneous boxes take 0.65 s, all 1000 of them. One more live box costs 0.35 MB of real
memory. exec into a running box is 0.79 ms against Docker's 43.3.
kern is in the fastest tier and does not win single-shot latency outright: bubblewrap is 0.8 ms
behind and the physical floor for unshare + exec is 1 to 2 ms. The gap that matters is to the
engines, ~132x, and bubblewrap is a launcher with no images, caps or lifecycle. Method, per-phase
breakdown, board numbers and the caveats: BENCHMARKS.md.
Namespaces, a pivot_root, 13 dangerous capabilities dropped before exec, an always-on seccomp
denylist of 33 syscalls, cgroup v2 limits, and a deny-by-default /dev. Where a boundary is
cooperative rather than kernel-enforced, SECURITY.md says so and names the bypass.
You do not have to take it on trust: pentest/ holds four adversarial suites that assert those boundaries against the kernel rather than against kern's own reporting, and they run without a registry account or a network.
sh pentest/run-with-local-registry.sh ./target/release/kern pentest/pentest-ports.shReport a vulnerability privately via GitHub Security Advisories or hello@getkern.dev.
| docs/INSTALL.md | install on Linux, WSL2 and ARM boards, with checksums |
| docs/RESOURCES.md | vcpu: / vdisk: / vgpio: and the two-verb model |
| docs/CONFIG.md | the kern.toml schema, field by field |
| docs/DOCKER-COMPAT.md | what of Docker works, what does not, and where it differs |
| docs/STORAGE.md · docs/EGRESS.md | volumes and the egress allowlist |
| BENCHMARKS.md · EDGE.md | measurements, and running on a Pi, Jetson or UNO Q |
| SECURITY.md · OPEN_ITEMS.md | the threat model, and the known gaps |
| ARCHITECTURE.md · CHANGELOG.md | how it is built, and what changed |
| examples/ · blog/ | ninety runnable scripts, and longer write-ups |
Embed it from Python or Node with kern-sandbox: a fresh box per call,
network off by default, hard caps, and a timeout the binding enforces.
0.6.32. Everything above works today and is tested: 693 Rust, 69 Python and 56 Node tests,
clippy-clean, cargo-deny-clean. Semver, pre-1.0: the CLI and config surface can still change
between minor versions, always called out in CHANGELOG.md. Releases are signed tags
and timestamped to Bitcoin (provenance/).
Issues and pull requests are welcome. CONTRIBUTING.md has the workflow and the gates; contributions are covered by the CLA.
Apache-2.0. See LICENSE and TRADEMARK.md.
