
kern: A fast, rootless sandbox and virtual assets runtime for immoderate workload, including untrusted and AI-generated code.
A real, kernel-enforced instrumentality successful ~3.5 ms, retired of 1 1.52 MB binary pinch nary daemon.
0 RAM astatine rest · nary daemon, nary socket, thing to commencement · 1 fixed binary, libc its only Rust dependency
No autochthonal Windows: usage WSL2. Install.
One binary that manages resources, of which isolation is the first. That is why location is no single statement for kern successful a comparison table: it is simply a instrumentality runtime, a sandbox, a assets slicer and a stack runner astatine once, successful 1.52 MB pinch nary daemon.
- A existent container. Real OCI images: pull, build from a Dockerfile, commit, push, save/load. A container from an image starts successful ~3.5 ms.
- A sandbox, ever rootless. User, PID, mount, network, UTS and IPC namespaces, an overlay or read-only guidelines pivoted in, a deny-by-default seccomp allowlist and cgroup v2 limits. One flag, --security-profile untrusted, is the full hardened bundle.
- Resource profiles, not conscionable isolation. CPU (vcpu:), memory, disk (vdisk:) and devices (vgpio:), declared erstwhile successful a kern.toml and attached by name. kern tally applies the aforesaid caps to a process connected the host, pinch nary sandbox astatine all. docs/RESOURCES.md
- Stacks, successful kern's ain format aliases successful Docker's. kern constitute <file> up takes a kern-compose.toml ([box.NAME] tables, pinch the assets profiles above) aliases the docker-compose.yml you already have, read arsenic written. One stack to 1 pod, services reaching each different by name.
- The devices astir them. ps, logs, exec, stats, inspect, wait, apical (a unrecorded TUI), doctor, positive a Python and Node SDK and an MCP server for agents.
Its full Rust dependency character is libc: JSON and OCI manifests are parsed by hand, and pull shells retired to the curl and tar already connected the instrumentality alternatively than linking a TLS stack. (1.52 MB is the size-optimized merchandise build; a plain cargo instal from root is 1.91 MB.)
-
Not a hypervisor. The bound is the Linux kernel, truthful a kernel privilege-escalation bug is an escape. Docker and Podman stock that condition, which is why gVisor and Firecracker exist.
Read pinch the tagline, that is 1 statement seen from some sides: untrusted and AI-generated codification is what kern is FOR, because you chose to tally it and ain the blast radius (agent tool-calls, CI jobs, build steps, codification cells). What it is not for is dispute codification from strangers, multi-tenant, connected a kernel you service different tenants from. kern does commencement rootless always, wherever Docker's is opt-in.
-
Not free of the userns trade. Its isolation is built connected an unprivileged personification namespace, a fertile root of kernel LPE bugs. SECURITY.md states this earlier immoderate claim.
-
Not a wall astir what you equine in. -v $HOME:/host gives the container your location directory: a mount is simply a spot determination you make, not a bound kern enforces. --net big and --privileged are opt-outs by name. (The 1 way kern refuses to hindrance is its ain runtime registry.)
-
Not a Docker Engine reimplementation. It speaks Docker's formats, not its API: nary overlay networks, nary plugins, nary Swarm. Matrix: docs/DOCKER-COMPAT.md.
-
Not a Kubernetes runtime. No CRI. Use containerd aliases CRI-O.
-
Not shipping GPU slices. On the roadmap, pinch nary GPU codification successful this edition, so there is thing present to spot aliases to onslaught yet.
What it does not cognize aliases does not do yet is successful OPEN_ITEMS.md alternatively than near for you to find.
kern needs a Linux kernel pinch unprivileged personification namespaces and cgroup v2. It runs connected Linux, WSL2 and ARM boards (Raspberry Pi · Jetson · Arduino UNO Q); location is no autochthonal Windows build, use WSL2 (kern ships a pre-baked WSL rootfs).
The quickest way is the merchandise binary: 1 fixed file, nary toolchain, and the book verifies its SHA256 earlier installing it.
It picks x86_64 aliases aarch64 for you, installs to ~/.local/bin (/usr/local/bin arsenic root, or KERN_INSTALL_DIR), and refuses to instal a download whose checksum does not match. Verifying by hand alternatively is 2 lines:
From source is the different route, and the full dependency character is 1 crate (libc), truthful it is short: clone, build and instal took 36 s connected a desktop (i7-14700KF), longer connected a mini ARM board.
That puts kern successful ~/.cargo/bin, which rustup adds to your PATH (open a caller shell, or source "$HOME/.cargo/env", if kern is not found).
The merchandise besides ships an aarch64 binary, a Windows .exe shim and a pre-baked WSL rootfs, each with its ain .sha256; the tag is GPG-signed and independently timestamped (provenance/).
kern expert tells you whether boxes will tally present earlier you try. Boards, WSL2 and the agelong form: docs/INSTALL.md. Common questions (Docker, bubblewrap, youki, E2B, Windows, the threat model): docs/FAQ.md.
Untrusted code, 1 emblem for the bundle:
--security-profile untrusted is the seccomp allowlist + --cap-drop ALL + --read-only successful one opt-in emblem (spell them retired by manus if you prefer); adhd --require-limits to garbage to commencement unless the memory/pids caps are really enforced. No web unless you ask, vulnerable capabilities dropped, seccomp ever on. Ninety runnable examples, each doing 1 thing: examples/.
Every publication verb besides answers successful JSON, truthful thing has to parse a table:
Your Docker Compose stack, without Docker Desktop
kern speaks docker-compose.yml. Point it astatine the stack you already person and kern constitute up runs it with nary daemon and nary Docker Desktop, the aforesaid connected Linux, WSL2 and ARM boards.
Both charismatic images start, web reaches db by work name, and the larboard is published to the host. Warm (images cached) the web tier serves successful ~0.3 s, and the stack costs only what postgres and adminer actually usage (~66 MB here) pinch zero daemon connected top, wherever Docker Desktop is simply a inheritance VM earlier your first container.
Official images that driblet to a non-root personification (postgres, redis, ...) want uidmap and a /etc/subuid line, and outbound image pulls want pasta; some are 1 apt instal connected a dev box, and kern doctor names either if it is missing. This is the section dev loop, not a accumulation orchestrator: nary Swarm, no overlay networks.
Run supplier aliases LLM-generated codification from your ain programme with kern-sandbox, a thin, dependency-free wrapper complete the kern binary. Every telephone runs successful a caller isolated box: web off, representation and pid caps, capabilities dropped, output bounded, and a timeout the binding itself enforces.
- Faults are data, not exceptions: a timeout, OOM-kill aliases blocked syscall is simply a section connected the result, not a raise. A caller container per telephone by default; Sandbox keeps a workspace crossed calls and a lukewarm kernel() keeps 1 expert for sub-millisecond cells (weaker isolation, by choice).
- Rich results without a Jupyter kernel: the past expression, display() and matplotlib figures come backmost captured, for illustration a notebook cell.
- Ships an MCP server (kern-mcp): a dependency-free stdio server that gives Claude Desktop, Cursor aliases immoderate MCP customer a section codification interpreter. Point the customer astatine it:
Tools: run_code (python/bash/node), write_file, read_file, list_files. Each telephone is simply a fresh network-off box; files persist crossed calls successful a workspace connected disk. Setup command, image and the other options: bindings/python/README.md.
Full API, Python and Node: bindings/python/README.md · bindings/node/README.md.
A portion is declared erstwhile successful ~/.config/kern/kern.toml and attached by name, to a sandboxed container aliases a bare process, pinch the aforesaid token.
Three kinds: vcpu: (CPU and memory), vdisk: (a size-capped scratch disk) and vgpio: (device nodes). Two of them, and the anchors they are carved from:
Profiles compose: respective connect to 1 box, and an definitive emblem thumps a profile's ain value. Every key is spelled for illustration its CLI flag, truthful cpus is --cpus and representation is --memory. A backend naming no declared excavation is refused erstwhile the config is read, not erstwhile the container runs. docs/RESOURCES.md has the field-by-field schema.
A vdisk: is simply a RAM-backed tmpfs erstwhile kern runs rootless, immoderate its backend says, and an ext4-on-loop image pinch a existent quota erstwhile it runs privileged. kern says which 1 you got, per profile, alternatively than letting you assume, and the size headdress is enforced either way.
vgpio: is chip-granular, not per-line. Asking for pins binds the full /dev/gpiochipN, and that characteristic instrumentality exposes each statement of that controller. pins = [17] does not restrict the box to statement 17: the kernel has nary per-line equine boundary, truthful the pin database is cooperative metadata rather than a boundary. Naming a instrumentality node, arsenic i2c supra does, grants that node and thing else.
| Daemon | no | yes (dockerd + containerd) | no |
| Rootless | yes, always | opt-in | yes |
| Cold start, bare box | ~2.3 ms | ~297 ms | ~293 ms |
| Cold start, from an OCI image | ~3.5 ms | ~297 ms | ~293 ms |
| Stop a work (init handles SIGTERM) | ~1.9 ms | ~310 ms | ~380 ms |
| Resident memory, thing running | 0 | 154 to 160 MB | 0 |
| Footprint | one 1.52 MB binary | daemon stack | multi-binary install |
| OCI images, propulsion / build / push | yes | yes | yes |
| docker-compose.yml | yes, publication as-is | yes | partial |
| Overlay networks, Swarm, CRI | no | yes | partial |
| GPU | on the roadmap | yes | yes |
Intel i7-14700KF, Linux 7.0.0, the merchandise binary, 1 book you tin tally yourself: python3 examples/benchmark.py. Yours will disagree pinch your CPU, kernel and filesystem.
| Cold commencement (bare box) | ~2.3 ms | ~2.3 ms | ~18.6 ms | ~293 ms | ~297 ms |
| 200 boxes successful parallel | ~0.11 s | ~0.16 s | ~0.35 s | ~44.8 s | ~16.2 s |
Three 1000 astatine erstwhile return ~2.2 s, and a unrecorded container costs ~0.3 MB of memory.
Two honorable notes. Nobody wins single-shot latency outright: the level for unshare + exec is 1 to 2 ms, truthful the full apical tier sits wrong its ain noise, and bubblewrap is simply a launcher pinch no images, caps aliases lifecycle. The spread that intends thing is to the engines, 2 orders of magnitude above.
Method, per-phase breakdown, committee numbers and each caveat: BENCHMARKS.md.
Namespaces, a pivot_root, 16 vulnerable capabilities dropped earlier exec, an always-on seccomp allowlist by default (moby's ain default select minus kern's 35 flight syscalls, which stay hard-killed; a syscall extracurricular the vetted group returns ENOSYS, and the wider denylist is the opt-out via KERN_SECCOMP=denylist), cgroup v2 limits (--require-limits refuses to commencement unless they bind), and a deny-by-default /dev. Where a bound is cooperative alternatively than kernel-enforced, SECURITY.md says truthful and names the bypass.
You do not person to return it connected trust: pentest/ holds 4 adversarial suites that assert those boundaries against the kernel alternatively than against kern's ain reporting, and they tally without a registry relationship aliases a network.
Report a vulnerability privately via GitHub Security Advisories aliases [email protected].
| docs/INSTALL.md | install connected Linux, WSL2 and ARM boards, from source |
| docs/DOCKER-COMPAT.md | what of Docker works, what does not, and wherever it differs |
| docs/RESOURCES.md · docs/CONFIG.md · docs/STORAGE.md · docs/EGRESS.md | the two-verb model, the kern.toml schema, volumes and egress |
| docs/THREAT_MODEL.md · SECURITY.md · OPEN_ITEMS.md | the threat exemplary (structured, past per-mechanism), and the known gaps |
| BENCHMARKS.md · EDGE.md | measurements, and moving connected a Pi, Jetson aliases UNO Q |
| examples/ · blog/ | ninety runnable scripts, and longer write-ups |
| bindings/python/README.md · bindings/node/README.md | the kern-sandbox SDK: embed kern successful Python aliases Node |
The halfway is done. Everything supra useful today: 840 Rust, 78 Python and 61 Node tests, clippy-clean, cargo-deny-clean, connected existent hardware: Linux, WSL2, Raspberry Pi 5, Jetson Orin Nano, Arduino UNO Q. v0.7.0 is the first published release. The CLI and config aboveground tin still change, ever called retired successful CHANGELOG.md.
Issues and propulsion requests are welcome. CONTRIBUTING.md has the workflow and the gates; contributions are covered by the CLA.
Alex, @realexhub. Commits travel from @getkerndev, the project's perpetrate identity.
The commits are not signed; the merchandise TAG is. That is what to verify: git verify-tag v0.7.0 against the cardinal successful provenance/, whose fingerprint is in SECURITY.md.
Apache-2.0. See LICENSE and TRADEMARK.md.
English (US) ·
Indonesian (ID) ·