Microsandbox Runtime
ContainerPub can execute cloud functions inside microsandbox microVMs β hardware-isolated KVM sandboxes β instead of Podman containers. Execution is delegated to a privileged runner sidecar that the backend drives over gRPC; Podman remains the source of truth for image builds. Enable it with CONTAINER_RUNTIME=microsandbox.
Architecture
dart_cloud_backend (Shelf)
β
ββ DockerService
β ββ image build βββΆ Podman (unchanged)
β ββ execution βββΆ MicrosandboxRuntime
β
ββ gRPC :8089 (bearer token)
β
ββ microsandbox-runner (privileged sidecar)
β SandboxRunnerService
β ββ MicrosandboxClient (Rust FFI)
β
ββ msb + libkrunfw
ββ KVM microVMs (one per invocation)
The runner owns the microsandbox runtime and all microVM lifecycle. The backend never loads the Rust FFI library itself β it talks to the runner with a small generated gRPC client (microsandbox_grpc_client).
Execution Flow
- Deploy: dart_cloud deploy builds the function image with Podman exactly as before.
- Invoke: the backend creates the per-execution directory under the shared functions-data path (request.json, logs) and asks the runner to run the image.
- Image transfer: deployment exports the image from Podman and streams it to the runnerβs cache under $MSB_HOME via the gRPC ImageLoad call. Later invocations reuse the cache.
- The sandbox bind-mounts the shared functions-data root, uses its invocation directory, and runs /runner/function; the function writes result.json and logs back over the shared mount β no network needed for the exchange.
- The runner removes the ephemeral sandbox; the backend then reads the shared files and records the execution.
Environment Contract
# Backend
CONTAINER_RUNTIME=microsandbox # podman is the default
MSB_RUNNER_URL=grpc://microsandbox-runner:8089
MSB_RUNNER_TOKEN=<shared-secret> # required for non-loopback
MSB_MIN_MEMORY_MB=128 # per-sandbox memory floor
# Runner sidecar
MSB_RUNNER_HOST=0.0.0.0
MSB_RUNNER_MAX_IMAGE_BYTES=2147483648 # streamed image cap
MSB_RUNNER_PORT=8089
MSB_RUNNER_TOKEN=<same-secret>
MSB_HOME=/var/lib/microsandbox # persistent state volume
MSB_RUNTIME_VERSION=0.6.8 # baked seed marker
The compose stack wires this as an opt-in profile: microsandbox-runner in deployment/infrastructure/podman-compose.backend.yml runs privileged with /dev/kvm and starts only under the microsandbox compose profile.
Shared Path Contract
Both the backend and the runner must mount the functions-data volume at the same absolute path. The backend passes mounts in podman short syntax (<source>:<FUNCTIONS_DATA_DIR>:Z,rshared): an absolute source maps the guest target to that runner-visible path, while a named-volume token (e.g. functions-data) resolves to the guest target itself because the compose stack mounts the same named volume at /app/functions in both services. Long-form type=bind,source=...,target=... mounts are also supported.
Networking
Deny by default: function sandboxes run with noNetwork: true regardless of the podman network name passed by the backend (podman networks such as logging_network are meaningless inside microVMs). Functions that need outbound HTTP must use the Podman runtime until an explicit runner-side egress allowlist exists. Selective telemetry egress (Telegraf UDP :8094) is an open production gate.
Health & Startup
The runnerβs Health RPC reports real readiness: ok is true only when virtualization is available (/dev/kvm on Linux, native Apple virtualization on macOS) and the microsandbox probe succeeds. With CONTAINER_RUNTIME=microsandbox, the backend fails fast at startup if the runner is unreachable or reports ok=false.
Persistent State & Upgrades
The runner image bakes the version-matched msb + libkrunfw bundle into /opt/microsandbox-seed with a .runtime-version marker. On start, the entrypoint compares the marker against $MSB_HOME/.runtime-version: on mismatch it replaces only the seeded runtime dirs (bin/, lib/), preserving the image cache and sandbox state; on match it seeds only missing files.
Compatibility & Rollback
The CloudDartFunction, CLI, and API contracts are unchanged. Invocation checks recover missing runner images automatically when the source image still exists in Podman. A controlled redeploy is also recommended for legacy functions not using the current @cloudFunction class shape, or to validate against the current injected entrypoint. Roll back at any time with CONTAINER_RUNTIME=podman.
Production Gates
Microsandbox execution is implemented but not yet production cleared. Open gates: KVM host acceptance, including compose healthcheck/depends_on wiring; an explicit network/telemetry allowlist; TLS/mTLS on the gRPC channel; an archive preflight size limit, and full Docker test-suite isolation.
Full operator guide: MICROSANDBOX_RUNTIME_MIGRATION.md at the repository root. Deployable probes: examples/microsandbox-smoke, examples/microsandbox-failure, examples/microsandbox-timeout.