ossein

module
v0.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 23, 2026 License: MIT

README

Ossein

The fastest macOS container builder in the solar system

(and minimalistic, rootless, daemonless, microVM-based container runtime)

TL;DR

# just build embeds the verified guest kernel + initfs INTO the binary —
# fully self-contained, no artifact paths needed:
just build
time ./.build/ossein run debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251 echo hi

# Local dev / bench A/B can override the embedded artifacts:
OSSEIN_KERNEL=/path/to/kernel-arm64 OSSEIN_INITFS=/path/to/initfs.ext4 ossein run debian:bookworm-slim@sha256:3783cc01769c7b2b1b83a5c5ad96c815348e28ed7da68e2e3687004faa906251 echo hi

just build is the only sanctioned build: go install .../cmd/ossein@<ver> can never work, deliberately — the //go:embed guest artifacts are produced by the harness (verified kernel fetch + in-repo initfs build) and are not part of the module zip.

Install

Requirements: macOS 26 or newer on Apple silicon. ossein boots its guest through Virtualization.framework; there is no daemon, nothing to install system-wide.

From a release

Every release ships ossein_<version>_darwin_arm64.tar.gz — ossein and its docker-shaped front ossein-docker, side by side — a checksums.txt, and a Sigstore bundle signed keylessly by the release workflow itself — there is no signing key anywhere to leak. Verify before trusting:

cosign verify-blob --bundle checksums.txt.sigstore.json \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity-regexp \
    'https://github.com/farcloser/ossein/\.github/workflows/release\.yaml@refs/tags/v.*' \
  checksums.txt
shasum -a 256 --check --ignore-missing checksums.txt
tar xzf ossein_*_darwin_arm64.tar.gz ossein ossein-docker

The binary is signed ad hoc with the Virtualization entitlement — there is no Apple developer account behind this project, so it carries no Developer ID and is not notarized. macOS therefore quarantines it as a download, and the first run is refused until you clear that bit yourself:

xattr -d com.apple.quarantine ossein
./ossein version

Clearing quarantine on an unverified download would be switching off a protection blind; after the cosign step above it is an informed decision, which is why the verification comes first.

From source
just build        # fetches + verifies the pinned guest kernel, builds the initfs, embeds both, codesigns
./.build/ossein doctor

just build is the only sanctioned build (see the note under TL;DR).

Releasing

From a clean main, just do release vX.Y.Z creates the signed tag and pushes it; the release workflow builds the binary, signs the checksums keyless (cosign, Fulcio) and publishes the GitHub release. Consumers verify it as described under "From a release" above.

Motivation

Running buildkitd on macOS is not new.

Docker and OrbStack obviously offer it. However, they are close source, moving targets, large system wide daemons that cannot be pinned nor sealed into a project hermetic tooling. Further, they are fairly large systems offering a lot more than just "build".

DIY-ers generally turn to lima, which is a great, extremely flexible project. However, it requires a lot of yak-shaving to isolate and pin per-project. It also runs full-blown linux systems, and like the other two, its feature surface is much larger than "just build".

If what you want is indeed "just build", an unprivileged build tool that runs on demand, is fast, ultra light-weight, can be pinned and sealed, with good isolation guarantees, you are on your own.

Ossein was built to bridge that gap:

  • everything can be pinned and sealed into per-project tooling (including the kernel)
  • single unprivileged binary, no system daemon
  • one-off micro-VM per build, in memory
  • fast

Usage(s)

The best and intended way to run ossein is through aqua, on a project's hermetic PATH. Flags are docker-shaped:

ossein pull debian@sha256:…                            # resolve + flatten into the local cache
ossein run --rm -v "$PWD:/w" -w /w debian@sha256:… sh -c 'make'
ossein run --rm --platform linux/amd64 debian@sha256:… uname -m   # amd64 via Rosetta
eval "$(ossein buildkit --detach)"                     # per-project buildkitd; prints BUILDKIT_HOST
ossein stop                                            # stop background instance(s)
docker, for scripts that expect one

ossein-docker is a docker-shaped front for the handful of docker invocations build scripts actually make — build, run, pull, stop, version — with the flags they actually pass, and nothing else: an unknown flag or subcommand is refused, never silently dropped. Installed as docker on a hermetic PATH, a script written against docker or podman runs unchanged on a mac with no daemon.

docker build -t app:dev --build-arg V=1 -f ci/Dockerfile .
docker run --rm -v "$PWD:/w" -w /w app:dev make        # the tag resolves locally, offline

run, pull and stop exec the ossein next to the binary. build talks to buildkitd through the buildkit client library: it starts this directory's buildkit microVM (ossein buildkit --detach, reused if already up), solves the Dockerfile with the context and Dockerfile as local mounts, and records every -t tag in ossein's image cache — flattened and ready, so the run that follows boots warm. Registry credentials come from docker's own store (docker login). --push and --output are not part of it: the image cache is the destination.

Where docker and ossein disagree, docker wins. A run or build that passes no --cpus/--memory gets the whole host — every CPU, all memory, backed lazily — as a container does under a daemon; ossein run's own 2 vCPU / 4 GiB default does not apply through the front. --cpus 1.5 rounds up to whole vCPUs, and --memory takes docker's units (8g, 8gb, 512MiB, 1.5g).

The first script written against it is build-posix.sh in forkcloser/curl, whose linux legs run in a digest-pinned debian container — podman on linux, this front on macOS, one invocation.

Persistent build cache (per project)

The micro-VM is throwaway and its rootfs lives in memory, so by itself a build keeps nothing. To make BuildKit's cache (content store, cache metadata, snapshots) survive and warm the next build, ossein backs /var/lib/buildkit with a per-project ext4 image on the host — created and formatted on first use (pure Go, no mkfs), reused thereafter.

The cache is keyed by directory, so it stays scoped to the project like the rest of the tooling:

cd myproject
eval "$(ossein buildkit --detach)"   # first run: creates the project's cache volume
# … build … (cache is populated)
ossein stop
eval "$(ossein buildkit --detach)"   # later: same dir → same cache, builds start warm
Where the cache lives

By default the image is stored centrally, keyed by the project directory, so it never touches your tree (no .gitignore, no Time Machine / cloud-sync churn on a large growing file):

~/Library/Application Support/ossein/buildkit/<hash>/cache.img   # persistent, sparse

The --cache flag controls this — it takes either a name or a path:

--cache value where the cache lives
(omitted) central, keyed by the current directory
a bare name (--cache api) central, keyed by that name — pin a stable key across a moved/renamed checkout, or share one cache between directories
a path (--cache ./.ossein/cache, /abs/path) project-local at that path (an auto-written .gitignore keeps the image out of version control)

Run ossein buildkit --print-cache [--cache …] to print the resolved directory without booting anything.

Operational notes
  • One writer — a cache volume is locked while in use; a second ossein buildkit for the same cache fails fast with an actionable message (run ossein stop first, or use --cache <name>) rather than corrupt it.
  • Clean shutdown flushes the cache — ossein stop sends SIGTERM and waits up to --grace (default 60s) for buildkitd to shut down and the cache to sync to disk before escalating to SIGKILL. Bump it if a very large cache ever needs longer; lower it to force-kill a stuck instance sooner.
  • Reclaim — caches are kept by design. ossein gc --prune-cache deletes the central ones not currently in use; plain ossein gc leaves them alone. Project-local caches live in your tree, so they're yours to manage.

Directories

Path Synopsis
guest
internal/guestagent
Package guestagent implements the SandboxContext service inside the guest microVM.
Package guestagent implements the SandboxContext service inside the guest microVM.
internal/httpd
Package httpd implements the minimal HTTP/1.1 server vminitd needs to serve Connect RPCs over vsock.
Package httpd implements the minimal HTTP/1.1 server vminitd needs to serve Connect RPCs over vsock.
internal/rootpath
Package rootpath resolves paths against a container rootfs the way a chroot would, through the kernel (openat2 RESOLVE_IN_ROOT).
Package rootpath resolves paths against a container rootfs the way a chroot would, through the kernel (openat2 RESOLVE_IN_ROOT).
internal/vmexec
Package vmexec is the ossein guest container runtime — the Go port of Apple's vmexec.
Package vmexec is the ossein guest container runtime — the Go port of Apple's vmexec.
vminitd command
Command vminitd is the ossein guest binary: one static linux/arm64 executable that is PID 1 inside the microVM.
Command vminitd is the ossein guest binary: one static linux/arm64 executable that is PID 1 inside the microVM.
hack
bench command
Command bench is the ossein guest microbenchmark suite: one static linux/arm64 binary that runs a single benchmark selected by --type, so the whole suite is a single artifact to cross-build and mount into a container.
Command bench is the ossein guest microbenchmark suite: one static linux/arm64 binary that runs a single benchmark selected by --type, so the whole suite is a single artifact to cross-build and mount into a container.
build-initfs command
Command build-initfs assembles the guest initfs as an UNCOMPRESSED newc cpio archive — the kernel unpacks it as the initramfs root, in RAM, with no block device involved.
Command build-initfs assembles the guest initfs as an UNCOMPRESSED newc cpio archive — the kernel unpacks it as the initramfs root, in RAM, with no block device involved.
vsockpeer command
Command vsockpeer is the GUEST half of the vsock proxy throughput bench (hack/vsockbench).
Command vsockpeer is the GUEST half of the vsock proxy throughput bench (hack/vsockbench).
internal
cli
Package cli holds the conventions every ossein command-line binary follows — the process logger, the --log-level vocabulary, the exit-status convention, the spelling of "the whole host" on --cpus and --memory — so that ossein and its docker-shaped front (cmd/ossein-docker) behave as one product without either importing the other's main package.
Package cli holds the conventions every ossein command-line binary follows — the process logger, the --log-level vocabulary, the exit-status convention, the spelling of "the whole host" on --cpus and --memory — so that ossein and its docker-shaped front (cmd/ossein-docker) behave as one product without either importing the other's main package.
protocol
Package protocol holds the constants the ossein HOST and the ossein GUEST must agree on exactly.
Package protocol holds the constants the ossein HOST and the ossein GUEST must agree on exactly.
rootfsblob
Package rootfsblob holds the rootfs blob's self-describing format contract: the byte patterns the HOST writes into the cached blob and the GUEST reads back to decide how to materialize it.
Package rootfsblob holds the rootfs blob's self-describing format contract: the byte patterns the HOST writes into the cached blob and the GUEST reads back to decide how to materialize it.
pkg
guest
Package guest is the typed client for the ossein guest agent — the PID-1 init inside the microVM (guest/vminitd + guest/internal/guestagent) — over its Connect-on-vsock control channel.
Package guest is the typed client for the ossein guest agent — the PID-1 init inside the microVM (guest/vminitd + guest/internal/guestagent) — over its Connect-on-vsock control channel.
guestartifacts
Package guestartifacts serves the guest boot artifacts (the Linux kernel and the vminitd initfs) that ossein hands to Virtualization.framework.
Package guestartifacts serves the guest boot artifacts (the Linux kernel and the vminitd initfs) that ossein hands to Virtualization.framework.
image
Package image resolves OCI images and serves their flattened rootfs, backed by primordium's content-addressable store (concurrency-safe, GC'd).
Package image resolves OCI images and serves their flattened rootfs, backed by primordium's content-addressable store (concurrency-safe, GC'd).
image/flatten
Package flatten squashes an OCI image's layer stack into one plain tar stream.
Package flatten squashes an OCI image's layer stack into one plain tar stream.
ocispec
Package ocispec turns run parameters into the OCI runtime spec that vminitd executes (via vmexec) inside the microVM.
Package ocispec turns run parameters into the OCI runtime spec that vminitd executes (via vmexec) inside the microVM.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL