How the iii-sandbox Worker Provides Ephemeral VM Execution Environments from OCI Rootfs
The iii-sandbox worker launches as an external child process, caches OCI rootfs images, and boots them inside libkrun micro-VMs with ephemeral overlays to provide isolated, short-lived execution environments.
The iii-sandbox worker is an external worker implementation in the iii-hq/iii repository that transforms standard OCI container images into lightweight, ephemeral virtual machines. Unlike traditional container runtimes, this worker extracts only the root filesystem, caches it locally, and executes commands inside hardware-virtualized micro-VMs through an overlay-based storage system.
Architecture Overview
When a driver's config.yaml specifies the worker class iii-sandbox, the III engine resolves this via the known-external table in engine/src/workers/external.rs. The engine spawns the binary iii-worker sandbox-daemon as a child process, piping stdout and stderr to prevent terminal contamination. This daemon registers 14 distinct triggers—including sandbox::create, sandbox::exec, sandbox::stop, and filesystem operations—through the III SDK entry point in crates/iii-worker/src/sandbox_daemon/mod.rs.
The architecture separates concerns across three layers:
- Orchestration layer: The engine manages worker lifecycle through
ExternalWorker::start_background_tasks - Daemon layer: The sandbox daemon handles OCI resolution, caching, and VM orchestration
- Virtualization layer: libkrun provides KVM-based micro-VMs with custom init systems
The Lifecycle of an Ephemeral Sandbox
Worker Launch and Registration
The lifecycle begins when ExternalWorker::start_background_tasks spawns iii-worker sandbox-daemon. The daemon immediately registers its API surface through functions like register_sandbox_create, register_sandbox_exec, and register_sandbox_stop in crates/iii-worker/src/sandbox_daemon/mod.rs. This registration makes the sandbox triggers available to the III SDK for remote invocation.
Image Resolution and Caching
When a client invokes sandbox::create, the daemon executes handle_create in crates/iii-worker/src/sandbox_daemon/create.rs. This process validates the request against an image allow-list, then resolves the image name to an OCI reference via the catalog module.
The rootfs handling follows a strict caching strategy:
- Check for a cached unpacked rootfs at
~/.iii/cache/<slug>/ - If missing and
auto_installis enabled, pull the OCI image usingcrates/iii-worker/src/sandbox_daemon/auto_install.rs - Extract and cache the filesystem for future reuse
This separation means the daemon never runs a full container engine—it only requires the extracted filesystem blob.
VM Boot Process
After caching, handle_create constructs an ephemeral overlay directory structure (merged, upper, and work directories) via overlay::OverlayLayout in crates/iii-worker/src/sandbox_daemon/overlay.rs. The daemon then invokes IiiWorkerLauncher::boot from crates/iii-worker/src/sandbox_daemon/adapters.rs to launch the micro-VM.
The boot sequence executes iii-worker __vm-boot (the same binary, re-executed) with flags specifying:
- Path to the cached rootfs (read-only)
- Overlay paths (writable upper layer)
- CPU and memory limits
- Unix sockets for control (
control.sock) and command execution (shell.sock)
First-boot provisioning includes platform-specific setup: macOS code-signing and extraction of libkrunfw (the KVM hypervisor runtime) plus the init.krun binary via ensure_libkrunfw and ensure_init_binary. The launcher polls shell.sock until a successful connection confirms the VM is alive before returning the sandbox ID to the caller.
Command Execution
Once booted, clients invoke sandbox::exec handled by handle_exec in crates/iii-worker/src/sandbox_daemon/exec.rs. The daemon opens a ShellRunner that communicates with the running VM over shell.sock using the iii-shell-client protocol.
Commands execute inside the overlay's merged view, inheriting environment variables set at boot time plus any per-execution env overrides. Output streams back to the caller with a 1 MiB cap per stream (stdout and stderr separately).
Filesystem Operations
The daemon provides ten filesystem triggers (sandbox::fs::ls, write, read, rm, etc.) implemented in crates/iii-worker/src/sandbox_daemon/fs.rs. These manipulate the overlay's upper and work layers using standard POSIX calls through iii-filesystem. Because each sandbox maintains an isolated overlay, all mutations disappear when the sandbox stops, ensuring true ephemerality.
Cleanup and Reaping
Resource cleanup operates through two mechanisms:
Idle reaping: A background task (run_reaper_loop in crates/iii-worker/src/sandbox_daemon/reaper.rs) monitors last_exec_at timestamps. Sandboxes exceeding idle_timeout_secs (default 300 seconds) receive automatic termination and overlay deletion.
Explicit stopping: The sandbox::stop trigger (handled by handle_stop in crates/iii-worker/src/sandbox_daemon/stop.rs) sends SIGTERM, waits 200ms, then escalates to SIGKILL. The overlay directory is then deleted, freeing RAM and CPU while leaving the cached rootfs intact for reuse.
Key Implementation Details
OCI Rootfs Handling
According to the source code in crates/iii-worker/src/sandbox_daemon/auto_install.rs, the auto-install logic pulls images only when missing from cache and validates them against the allow-list. This design ensures fast sandbox creation for subsequent uses of the same image while maintaining security boundaries.
Overlay Filesystem
The overlay::OverlayLayout creates a unique directory triad for each sandbox:
- upper/: Captures all write operations
- work/: Required for overlay filesystem internals
- merged/: The unified view presented to the VM
Reads fallback to the immutable OCI rootfs when files are absent from the upper layer. When sandbox::stop executes, the daemon recursively deletes these three directories, instantly reverting the filesystem state.
Resource Constraints
The daemon enforces hierarchical limits defined in the configuration:
- Per-image caps:
default_cpus,default_memory_mb, andper_image_capsrestrict individual sandboxes - Global limits:
max_concurrent_sandboxesprevents resource exhaustion - Error handling: Requests exceeding limits return S-code
S400before VM allocation occurs
Code Examples
TypeScript SDK
import { registerWorker } from 'iii-sdk';
const iii = registerWorker('ws://127.0.0.1:49134');
// Boot a sandbox from the built-in "python" image
const { sandbox_id } = await iii.trigger({
function_id: 'sandbox::create',
payload: { image: 'python', cpus: 1, memory_mb: 512 },
timeoutMs: 300_000,
});
// Run a command inside the VM
const out = await iii.trigger({
function_id: 'sandbox::exec',
payload: {
sandbox_id,
cmd: 'python3',
args: ['-c', 'print(2 + 2)'],
},
timeoutMs: 35_000,
});
console.log(out.stdout); // → "4\n"
// Clean up
await iii.trigger({
function_id: 'sandbox::stop',
payload: { sandbox_id, wait: true },
});
Python SDK
from iii import register_worker
iii = register_worker('ws://127.0.0.1:49134')
# Create ephemeral VM
res = await iii.trigger({
"function_id": "sandbox::create",
"payload": {"image": "python", "cpus": 1, "memory_mb": 512},
"timeout_ms": 300_000,
})
sandbox_id = res["sandbox_id"]
# Execute command
out = await iii.trigger({
"function_id": "sandbox::exec",
"payload": {"sandbox_id": sandbox_id,
"cmd": "python3",
"args": ["-c", "print(2 + 2)"]},
"timeout_ms": 35_000,
})
print(out["stdout"]) # → "4\n"
# Terminate sandbox
await iii.trigger({
"function_id": "sandbox::stop",
"payload": {"sandbox_id": sandbox_id, "wait": True},
})
CLI Shortcut
iii sandbox run python -- python3 -c 'print(2 + 2)'
# prints "4" and automatically stops the VM
Summary
- External process model: The
iii-sandboxworker runs asiii-worker sandbox-daemon, spawned by the engine viaExternalWorker::start_background_tasksinengine/src/workers/external.rs. - OCI to VM pipeline: The daemon resolves OCI references, caches unpacked rootfs at
~/.iii/cache/<slug>/, and boots them usingIiiWorkerLauncher::bootwith libkrun virtualization. - Ephemeral storage: Each sandbox receives an isolated overlay (upper/work/merged directories) that is deleted on stop, while the cached rootfs remains for reuse.
- Socket-based communication: Commands flow through
shell.sockusing theiii-shell-clientprotocol, with output capped at 1 MiB per stream. - Automatic lifecycle management: Idle sandboxes exceed
idle_timeout_secs(default 300s) are reaped byrun_reaper_loop, and explicit stops trigger SIGTERM → SIGKILL sequences.
Frequently Asked Questions
How does iii-sandbox differ from Docker or containerd?
Unlike Docker or containerd, the iii-sandbox worker does not run a container engine or manage daemon processes. According to the implementation in crates/iii-worker/src/sandbox_daemon/create.rs, it extracts only the OCI rootfs layer, caches it locally, and boots a libkrun micro-VM with that filesystem mounted read-only. Commands execute inside hardware-virtualized environments rather than kernel namespaces, providing stronger isolation boundaries while maintaining sub-second startup times for cached images.
Where are the OCI images cached and how is storage managed?
The daemon stores unpacked rootfs directories under ~/.iii/cache/<slug>/ as implemented in crates/iii-worker/src/sandbox_daemon/auto_install.rs. These cached layers persist across sandbox restarts for fast subsequent creation. However, each sandbox instance receives its own ephemeral overlay directory (created by overlay::OverlayLayout in crates/iii-worker/src/sandbox_daemon/overlay.rs) that is deleted when the sandbox stops via handle_stop in crates/iii-worker/src/sandbox_daemon/stop.rs. This design separates immutable image data from mutable sandbox state.
What happens if a sandbox exceeds resource limits?
The daemon validates requests against default_cpus, default_memory_mb, per_image_caps, and max_concurrent_sandboxes before booting. Requests exceeding these limits immediately return S-code S400 without spawning a VM, as defined in the resource enforcement logic. For sandboxes that exceed idle time, the run_reaper_loop in crates/iii-worker/src/sandbox_daemon/reaper.rs automatically terminates them after idle_timeout_secs (default 300 seconds) of inactivity.
Can I run custom OCI images or only built-in ones?
The sandbox supports custom OCI images when configured with an allow-list. The handle_create function in crates/iii-worker/src/sandbox_daemon/create.rs validates image names against this list before resolution. If auto_install is enabled in the configuration, the daemon automatically pulls, extracts, and caches unauthorized but valid OCI references using the catalog module and auto_install.rs logic. Images must provide a standard Linux rootfs compatible with libkrun's virtualization layer.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →