loam.

Firecracker sandboxes on the Kubernetes you already run.

Idle sandboxes save their memory and disk to S3, releasing VM memory. The next request restores their processes on a node with room.

Self-hosted, x86_64 with KVM only. No hosted service. loam-api runs as a single replica, so restarts interrupt the API and sandbox URLs. See isolation limits and E2B gaps.

# point the E2B SDK at your loam
pip install e2b
export E2B_DOMAIN=e2b.loam.example.com
export E2B_API_KEY=loam_...
from e2b import Sandbox

sbx = Sandbox.create()
print(sbx.commands.run("uname -a").stdout)
sbx.pause()     # snapshot to S3, VM off the node
sbx.connect()   # wake it, processes intact

Across the unmodified official Python and JS SDKs, 26 of 26 conformance steps pass for the supported surface. Template builds are unsupported. See E2B coverage.

Sleep and wake

A Postgres record tracks each sandbox. Long-lived nodelet pods run the VMs, so waking needs no new pod.

Scroll the diagram horizontally →

RUNNING PAUSED RUNNING node A · nodelet Firecracker VM S3 snapshot memory + disk node B · nodelet Firecracker VM pause wake VM memory released disk cache remains Idle after 300 s by default snapshot in your bucket Processes intact memory loaded lazily

Wake prefers the node holding the snapshot, then any node with room. Architecture · Primer

Snapshot timings

Log scale begins at 28 ms. Each bar has its own test condition.

Scroll the chart horizontally →

28 ms 320 ms 13 s Resume on the same node Single node · XFS reflinks 29 ms Fork from a memory checkpoint Single node · XFS reflinks 28 ms Pause memory and disk Single node · XFS reflinks 320 ms Wake on another node Cross-node · 2 GiB base template · lazy memory 0.42 s Wake saved state after node loss Cross-node · 2 GiB base template 5.8 s Drain with two awake sandboxes Cross-node · 2 GiB base template 13 s

Measured on x86 bare-metal k3s nodes with Garage as the store. Snapshot operations, not cold starts or percentiles. Lost-node wake restores saved paused or stopped state. Awake, unsaved work is lost. Test write-up

What the adapter serves

Checkpoints and forks are available through loam's native API. Full coverage and differences

Where sandboxes run

ProjectRuntimeDeployment
Hosted E2BFirecracker on E2B's machinesHosted service
E2B self-hostedNomad and ConsulTerraform. GCP supported, AWS beta
scitix/agent-sandboxWarm pod pools. MicroVMs plannedKubernetes operator, E2B-compatible server
kubernetes-sigs/agent-sandboxKubernetes-native sandbox APIAlpha, no E2B API
loamFirecracker in nodelets, snapshots while idleKubernetes, kustomize base and overlay

What a sandbox can reach

The nodelet enforces the boundary outside the guest. A sandbox with egress rules gets TCP over IPv4 only.

Scroll the diagram horizontally →

Firecracker VM guest environment __loam_key__ placeholder only nodelet · outside the guest DNS forwarder allowed names, private answers stripped SNI / Host-checking proxy resolves and dials the destination itself Secret broker placeholder → real value on the wire only for the secret's configured hosts Internet allowed by name exact or wildcard Private ranges blocked Node · pod network · LAN

Brokered values stay out of guest memory, disk and snapshots. Secrets the application writes itself are outside that protection.

Sandboxes have OIDC identity. VMs share their unprivileged nodelet's cgroup and memory limit.

What you need

Follow the install guide with the kustomize base and example overlay.

git clone https://github.com/arugula-salad/loam
cp -r loam/deploy/examples/basic my-loam
# set your domain, store URL, ingress and secrets in my-loam
kubectl kustomize my-loam | less
kubectl apply -k my-loam

For single-machine development, the local recipe uses an in-memory database that disappears on exit.

What would help

Send install reports from Talos, kubeadm, Hetzner or OVH bare metal, or cloud instances with nested virtualization. Contributions toward per-VM cgroups and E2B gaps would help.

Network after a move

A moved sandbox lost networking for 30 seconds. Random bridge MACs left stale guest ARP entries. Every node's bridge now uses a fixed MAC.

Chrome through the proxy

Headless Chrome's ECH GREASE triggered the egress filter's ECH rejection. The proxy now judges the outer SNI name.

Start with CONTRIBUTING.md. Report vulnerabilities privately through SECURITY.md.