Pre-alpha — APIs, wire formats, and behavior may change without notice. Expect breaking changes; use with caution.
emberd

Sandbox Lifecycle

What create, exec, and delete actually do — the real code paths in the Firecracker-backed Manager.

A sandbox is one Firecracker microVM. The sandbox.Manager interface has exactly three methods, and the HTTP API maps one endpoint to each:

type Manager interface {
	Create(ctx context.Context, languagePack string) (*Sandbox, error)
	Exec(ctx context.Context, id string, req proto.ExecRequest) (proto.ExecResult, error)
	Delete(ctx context.Context, id string) error
}

The Firecracker-backed implementation lives in pkg/sandbox/firecracker.

Create — boot a microVM

POST /sandboxesManager.Create:

  1. Resolve the language pack. Look up languagePack in the registry. An unknown name returns ErrUnknownPack → HTTP 400. This happens before any VM work, so it's cheap.

  2. Allocate identity and workspace. Generate sb_<hex>, create ${TMPDIR}/emberd/<id>/, open vm.log.

  3. Set up the control channel. Allocate a guest context ID (CID, counting up from 3) and pick the host vsock socket path <dir>/vsock.sock.

  4. Build the Firecracker config:

    • kernel = vmlinux-6.1.155, initrd = emberd-initramfs.cpio
    • rootfs drive = the pack's squashfs, read-only, root device (/dev/vda)
    • a hybrid-vsock device pointing at vsock.sock + the guest CID
    • 1 vCPU, 256 MiB (configurable)
    • kernel args = base args plus emberd.interpreter=<pack interpreter>
  5. Launch the VMM. Build the firecracker command (custom binary path, per-VM API socket, console wired to a log file) and Start it under a background context that lives for the VM's whole lifetime — not the HTTP request context, which would cancel the VM when the request returns.

  6. Record the handle in the manager's map and return { "id": "sb_..." } with HTTP 201.

  7. Wait for readiness. Before returning, Create blocks on waitReady, which polls the guest vsock control plane (50ms interval, BootTimeout default 15s). A successful hybrid-vsock CONNECT/OK handshake only happens once emberd-init is past bootstrap and listening, so it's a precise readiness signal — not a fixed sleep. If the guest never comes up, the half-booted VM is torn down and an error returned.

Because Create waits for the guest to actually accept on vsock (~400ms on the reference host), a returned sandbox is immediately usable — an exec issued with zero delay succeeds on the first try, no client-side retry needed.

Exec — run code in the guest

POST /sandboxes/{id}/execManager.Exec:

  1. Look up the live VM by ID (unknown → ErrNotFound404).
  2. proto.DialGuest(vsockUDS, GuestPort) — connect to the host vsock socket and perform the Firecracker hybrid-vsock CONNECT/OK handshake.
  3. Set a deadline on the connection: timeout_ms + 10s, or 60s if no timeout was given, so a wedged guest can't hang the request.
  4. WriteMessage(conn, ExecRequest) then ReadMessage(conn, &ExecResult).
  5. Map the result to the HTTP response.

Inside the guest, emberd-init writes the code to a temp file, runs it under the pack's interpreter with the request's stdin piped in, and captures stdout/stderr/exit. A non-zero exit from your program is a normal result (exit_code set, error empty); only a failure to launch the interpreter populates error. See the control plane for the wire details and the guest rootfs for how the interpreter runs.

Delete — tear it down

DELETE /sandboxes/{id}Manager.Delete:

  1. Remove the handle from the map (unknown → ErrNotFound404).
  2. StopVMM() sends SIGTERM to the firecracker process — a clean VMM shutdown.
  3. Wait with a 5-second bound; cancel the VM's context (which kills the process if the graceful stop stalled).
  4. RemoveAll the work directory.

The per-VM tmpfs overlay dies with the VM, so there's nothing to garbage-collect inside the guest — the writable layer simply ceases to exist.

State machine

State machine: POST /sandboxes moves from (none) to Running; POST /sandboxes/{id}/exec is a self-loop on Running (a round-trip over vsock); DELETE /sandboxes/{id} moves from Running to gone (VMM killed, work dir removed).

There is no "paused" or "stopped-but-kept" state in v0.1 — a sandbox is either running or gone. Snapshotting changes that in v0.2.

On this page