docs/sdk/rust/sandbox.mdx
Create and control a microVM sandbox: boot it from an image, run commands, stream logs and metrics, then shut it down. See Overview for configuration examples and Lifecycle for state management.
For local runtime installation and verification, see Runtime setup.
fn builder(name: impl Into<String>) -> SandboxBuilder
let sb = Sandbox::builder("api")
.image("python")
.create()
.await?;
Create a builder for configuring a new sandbox. The builder lets you set the image, resources, volumes, networking, secrets, and other options before booting the VM. Sandbox names must be non-empty and no longer than 128 UTF-8 bytes. See SandboxBuilder for all available options.
async fn get(name: &str) -> MicrosandboxResult<SandboxHandle>
let handle = Sandbox::get("api").await?;
println!("{:?}", handle.status());
Get a handle to an existing sandbox (running or stopped). The handle provides status, configuration, and lifecycle control without requiring a full connection to the guest agent.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name</code><span className="msb-type">&str</span></div> <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#sandboxhandle">SandboxHandle</a></div> <div className="msb-param-desc">Handle with status and lifecycle control.</div> </div> </div>async fn list() -> MicrosandboxResult<SandboxPage>
let page = Sandbox::list().await?;
for h in page.sandboxes {
println!("{} - {:?}", h.name(), h.status());
}
Return the first page of sandboxes (running, stopped, and crashed), ordered newest first. The default page size is 20.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">SandboxPage</span></div> <div className="msb-param-desc">Handles in this page and an optional cursor for the next page.</div> </div> </div>async fn list_with(
configure: impl FnOnce(SandboxListBuilder) -> SandboxListBuilder,
) -> MicrosandboxResult<SandboxPage>
Return a configured page of sandboxes. Limits must be between 1 and 100. Labels are AND-matched before pagination.
<Accordion title="Example">let page = Sandbox::list_with(|list| {
list.limit(50).label("role", "worker")
}).await?;
if let Some(cursor) = page.next_cursor {
let next_page = Sandbox::list_with(|list| {
list.limit(50).cursor(cursor).label("role", "worker")
}).await?;
}
async fn remove(name: &str) -> MicrosandboxResult<()>
Sandbox::remove("api").await?;
Delete a stopped sandbox by name. Locally, this removes the same state as sb.remove_persisted(); see Remove for the exact deletion scope. Unlike remove_persisted(), this associated function routes through the default backend and also supports cloud sandboxes. Fails if the sandbox is still running—stop it first.
async fn start(name: &str) -> MicrosandboxResult<Sandbox>
let sb = Sandbox::start("api").await?;
Restart a previously stopped sandbox. The VM reboots using the persisted configuration. The sandbox enters attached mode - it stops when your process exits.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name</code><span className="msb-type">&str</span></div> <div className="msb-param-desc">Name of a stopped sandbox, up to 128 UTF-8 bytes.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div> <div className="msb-param-desc">Running sandbox.</div> </div> </div>async fn start_detached(name: &str) -> MicrosandboxResult<Sandbox>
Restart a stopped sandbox in detached mode. The sandbox survives after your process exits.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name</code><span className="msb-type">&str</span></div> <div className="msb-param-desc">Name of a stopped sandbox, up to 128 UTF-8 bytes.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div> <div className="msb-param-desc">Running sandbox.</div> </div> </div> <p className="msb-member-group">Instance methods</p>fn config(&self) -> &SandboxConfig
println!("{} MiB", sb.config().memory_mib);
Access the sandbox's full configuration.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#sandboxconfig">&SandboxConfig</a></div> <div className="msb-param-desc">Sandbox configuration.</div> </div> </div>async fn detach(self)
sb.detach().await; // keeps running in the background
Release the handle without stopping the sandbox. The sandbox continues running as a background process. Reconnect later with Sandbox::get().
<Tooltip tip="Not available on microsandbox cloud; use a graceful stop."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn drain(&self) -> MicrosandboxResult<()>
sb.drain().await?;
Start a graceful drain. Existing commands run to completion, but new exec calls are rejected. The sandbox transitions to Stopped when all in-flight commands finish. Useful for zero-downtime rotation of worker sandboxes.
<Tooltip tip="Not available on microsandbox cloud; use a graceful stop."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn request_drain(&self) -> MicrosandboxResult<()>
Request graceful drain and return once the request is sent. Pair with wait_until_stopped() when the caller needs stopped-state observation.
fn fs(&self) -> SandboxFsOps<'_>
sb.fs().write("/tmp/hello.txt", "hi").await?;
Get a filesystem handle for reading and writing files inside the running sandbox. See Filesystem for API details.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="/sdk/rust/filesystem">SandboxFsOps</a></div> <div className="msb-param-desc">Filesystem handle.</div> </div> </div><Tooltip tip="Not available on microsandbox cloud; use a graceful stop."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn kill(&self) -> MicrosandboxResult<()>
sb.kill().await?; // SIGKILL, no graceful shutdown
Force-terminate the sandbox immediately with SIGKILL. No graceful shutdown - use when the sandbox is unresponsive. Waits up to five seconds for stopped-state observation after the kill request. Pending writes that the workload hasn't fsync'd may be lost, same durability semantics as a sudden power loss on a physical machine. Prefer stop() for graceful shutdown that gives the workload a chance to flush.
<Tooltip tip="Not available on microsandbox cloud; use a graceful stop."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn kill_with_timeout(&self, timeout: Duration) -> MicrosandboxResult<()>
Force-terminate the sandbox and wait up to timeout for stopped-state observation.
<Tooltip tip="Not available on microsandbox cloud; use a graceful stop."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn request_kill(&self) -> MicrosandboxResult<()>
Request force termination and return once the request is sent, without waiting for stopped-state observation.
<Tooltip tip="Resource metrics are not available on microsandbox cloud; use an external monitoring system."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn metrics(&self) -> MicrosandboxResult<SandboxMetrics>
let m = sb.metrics().await?;
println!("cpu {:.1}% · mem {} MiB", m.cpu_percent, m.memory_bytes / 1_048_576);
Get a point-in-time snapshot of the sandbox's resource usage: CPU, memory, disk I/O, network I/O, optional upper disk usage, and uptime.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#sandboxmetrics">SandboxMetrics</a></div> <div className="msb-param-desc">Resource metrics.</div> </div> </div><Tooltip tip="Resource metrics are not available on microsandbox cloud; use an external monitoring system."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn metrics_stream(&self, interval: Duration) -> impl Stream<Item = MicrosandboxResult<SandboxMetrics>>
use futures::StreamExt;
let mut stream = sb.metrics_stream(Duration::from_secs(1));
while let Some(snapshot) = stream.next().await {
println!("{:.1}%", snapshot?.cpu_percent);
}
Stream resource metrics at a regular interval. Returns an async stream that yields a new snapshot every interval duration.
<Tooltip tip="Bounded log reads are not available on microsandbox cloud; follow live with log streaming and persist output externally."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn logs(&self, opts: &LogOptions) -> MicrosandboxResult<Vec<LogEntry>>
use microsandbox::sandbox::{LogOptions, LogSource, Sandbox};
let handle = Sandbox::get("web").await?;
// Default: all user-program output, regardless of pipe/pty mode
let entries = handle.logs(&LogOptions::default())?;
for e in entries {
let source = match e.source {
LogSource::Stdout => "OUT",
LogSource::Stderr => "ERR",
LogSource::Output => "PTY",
LogSource::System => "SYS",
};
println!(
"[{}] {} {:?}: {}",
e.timestamp.to_rfc3339(),
source,
e.session_id,
String::from_utf8_lossy(&e.data).trim_end()
);
}
// Filtered: last 50 entries from the past hour, including system lines
let recent = handle.logs(&LogOptions {
tail: Some(50),
since: Some(chrono::Utc::now() - chrono::Duration::hours(1)),
sources: vec![
LogSource::Stdout,
LogSource::Stderr,
LogSource::Output,
LogSource::System,
],
..Default::default()
})?;
Read captured output from the sandbox's exec.log. Backed by an on-disk JSON Lines file the runtime writes via the relay tap. Works on running and stopped sandboxes alike; there is no protocol traffic. The same method is available on SandboxHandle for callers that don't want to start the sandbox first.
The default sources are Stdout, Stderr, and Output (PTY-merged). Pass LogSource::System to also include synthetic lifecycle markers and runtime/kernel diagnostic lines. logs() is synchronous because it's a pure file read.
<Tooltip tip="Not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn ping(&self) -> MicrosandboxResult<SandboxPingResult>
let result = sb.ping().await?;
println!("{} reachable in {:?}", result.name, result.latency);
Check whether the running sandbox's guest agent is reachable. This sends core.ping, returns the SDK-measured round-trip latency, and does not refresh the sandbox idle timer.
<Tooltip tip="Not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
async fn touch(&self) -> MicrosandboxResult<SandboxTouchResult>
let result = sb.touch().await?;
println!("{} activity seq {}", result.name, result.activity_seq);
Explicitly refresh the running sandbox's idle timer. This sends core.touch; use it when keeping an idle sandbox alive is intentional.
<Tooltip tip="modify is not available on microsandbox cloud; recreate the sandbox with the new configuration."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn modify(&self) -> SandboxModificationBuilder
let plan = sb.modify()
.cpus(4) // live when 4 <= max_cpus
.memory(4096) // live when 4096 MiB <= max_memory
.env("MODE", "prod") // future execs only; the plan warns about this
.apply()
.await?;
for r in &plan.resize_status {
println!("{:?}: requested {} · actual {} · {:?}", r.resource, r.requested, r.actual, r.state);
}
Plan or apply a configuration change. Set what to change (CPUs, memory, env vars, labels, workdir, secrets), then call dry_run() to preview or apply() to commit; both return a SandboxModificationPlan labeling each change live, next start, requires restart, or unsupported. Apply is all-or-nothing.
CPU and memory resize live within the max_cpus / max_memory ceilings; raising a ceiling requires a restart. Env and workdir changes affect future execs only. On a stopped sandbox, changes are saved for the next boot.
See SandboxModificationBuilder for all setters and msb modify for the CLI.
fn name(&self) -> &str
Get the sandbox name.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">&str</span></div> <div className="msb-param-desc">Sandbox name, up to 128 UTF-8 bytes.</div> </div> </div><Tooltip tip="On microsandbox cloud this is false; the cloud worker owns the sandbox process, not your handle."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn owns_lifecycle(&self) -> bool
Whether this handle owns the sandbox lifecycle. true in attached mode (sandbox stops when your process exits), false in detached mode.
async fn remove_persisted(&self) -> MicrosandboxResult<()>
sb.stop().await?;
sb.remove_persisted().await?;
Delete this stopped sandbox's local persisted state. This is the receiver-based form to use when you still hold the Sandbox instance; it is local-only and has exactly the same local deletion scope as Sandbox::remove(name). It does not perform additional cleanup. See Remove for what is deleted and which external resources are preserved.
async fn request_stop(&self) -> MicrosandboxResult<()>
Request graceful shutdown and return once the request is sent, without waiting for stopped-state observation. Pair with wait_until_stopped() when the caller needs the terminal state.
async fn stop(&self) -> MicrosandboxResult<()>
sb.stop().await?;
Gracefully shut down the sandbox. Lets the sandbox finish writing any pending data to disk before it exits, so files written inside the sandbox aren't lost across a later restart. Waits up to ten seconds for a clean exit; if the sandbox is still running after that, it is force-killed.
async fn stop_with_timeout(&self, timeout: Duration) -> MicrosandboxResult<()>
Gracefully shut down the sandbox with an explicit timeout before escalation. Duration::ZERO skips graceful shutdown and force-kills immediately.
async fn stop_and_wait(&self) -> MicrosandboxResult<ExitStatus>
let status = sb.stop_and_wait().await?;
println!("exited: {}", status.success());
Stop the sandbox and wait for the exit status. This is a local-backend compatibility helper; prefer stop() or stop_with_timeout() when the caller only needs stopped-state observation.
async fn wait(&self) -> MicrosandboxResult<ExitStatus>
let status = sb.wait().await?;
Block until the sandbox exits on its own (without triggering a stop). Returns the exit status.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="/sdk/rust/execution#exitstatus">ExitStatus</a></div> <div className="msb-param-desc">Exit code and success flag.</div> </div> </div>async fn wait_until_stopped(&self) -> MicrosandboxResult<SandboxStopResult>
Block until the sandbox is observed in a terminal non-running state. Owned local sandboxes can include process exit details; detached, name-addressed, and cloud-backed sandboxes report the observed backend state.
Returns
| Type | Description |
|---|---|
SandboxStopResult | Observed terminal sandbox state |
Builder for configuring a sandbox before creation. Obtained via Sandbox::builder(name). Every setter returns Self, so calls chain. Examples are shown on the methods where usage is non-obvious.
async fn build(self) -> MicrosandboxResult<SandboxConfig>
Materialize the SandboxConfig without booting the sandbox. Validates the configuration and, if from_snapshot was called, opens the snapshot manifest to pin its image reference and upper-layer source. For booting, use create instead; call detached(true) first for background mode. create() calls build internally.
fn cpus(self, count: u8) -> Self
Set the number of virtual CPUs. This is a limit, not a reservation. Default: 1.
<Tooltip tip="On microsandbox cloud these ceilings are not carried; the maximum is pinned to the initial value. Recreate the sandbox to resize."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn max_cpus(self, count: u8) -> Self
Set the boot-time maximum possible virtual CPU capacity. This reserves the envelope a sandbox can use after restart-backed changes and future live CPU activation; it does not increase the effective vCPU count by itself.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>count</code><span className="msb-type">u8</span></div> <div className="msb-param-desc">Maximum possible vCPUs.</div> </div> </div>async fn create(self) -> MicrosandboxResult<Sandbox>
Boot the sandbox in attached mode. The sandbox stops when your process exits.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#instance-methods">Sandbox</a></div> <div className="msb-param-desc">Running sandbox.</div> </div> </div>fn detached(self, detached: bool) -> Self
let sb = Sandbox::builder("worker")
.image("python")
.detached(true)
.create()
.await?;
sb.detach().await;
Choose whether the sandbox is created in detached/background mode. Detached sandboxes survive the creating process. Defaults to false.
async fn create_detached(self) -> MicrosandboxResult<Sandbox>
let sb = Sandbox::builder("worker")
.image("python")
.create_detached()
.await?;
sb.detach().await;
Boot the sandbox in detached mode. This is a compatibility helper for .detached(true).create(). Prefer detached(true) with create() for new code so attached and detached creation use the same flow.
fn disable_network(self) -> Self
Fully disable networking. No network interface is created.
fn entrypoint(self, cmd: impl IntoIterator<Item = impl Into<String>>) -> Self
Override the image ENTRYPOINT used by default-workload execution. Sandbox::exec_default combines it with the effective CMD. Literal Sandbox::exec, Sandbox::attach, and Sandbox::shell calls ignore it.
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self
Set an environment variable visible to all commands. Can be called multiple times. Per-command env vars (via exec_with) are merged on top.
<Tooltip tip="On microsandbox cloud, the hostname is assigned by the platform; a value set here is ignored."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn hostname(self, hostname: impl Into<String>) -> Self
Set the guest hostname.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>hostname</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Hostname.</div> </div> </div>fn idle_timeout(self, secs: u64) -> Self
Auto-drain the sandbox after this many seconds of inactivity (no active exec sessions). Enforced on the host side.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>secs</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Idle timeout in seconds.</div> </div> </div>fn cmd(self, cmd: impl IntoIterator<Item = impl Into<String>>) -> Self
Override the image CMD used by default-workload execution. An empty array explicitly clears the image CMD. This describes durable configuration and does not execute anything during create().
let sb = Sandbox::builder("worker")
.image("example/worker:latest")
.cmd(["worker.py", "--once"])
.create()
.await?;
fn init(self, cmd: impl Into<PathBuf>) -> Self
let sb = Sandbox::builder("worker")
.image("jrei/systemd-debian:12")
.init("auto")
.create()
.await?;
Hand off PID 1 inside the guest to cmd after agentd finishes its boot-time setup. The agent forks; the parent execs the init and becomes PID 1, the agent continues as a child process. See Custom init system for image picks, shutdown semantics, and tradeoffs.
cmd is either an absolute path inside the guest rootfs or the literal "auto". Auto first honors a known init at the start of the image ENTRYPOINT, such as /init in s6-overlay images, then falls back to probing /sbin/init, /lib/systemd/systemd, and /usr/lib/systemd/systemd inside the guest. When attached msb run uses an image-declared init entrypoint, the remaining ENTRYPOINT plus CMD or trailing command is passed to that init instead of direct-executed through agentd. For init binaries that take argv or extra env (rare), use init_with.
fn init_with(
self,
cmd: impl Into<PathBuf>,
f: impl FnOnce(InitOptionsBuilder) -> InitOptionsBuilder,
) -> Self
let sb = Sandbox::builder("worker")
.image("jrei/systemd-debian:12")
.init_with("/lib/systemd/systemd", |i| i
.args(["--unit=multi-user.target"])
.env("container", "microsandbox"))
.create()
.await?;
Like init, but with a closure-builder for argv and env vars. Mirrors exec_with in shape. The builder exposes arg, args, env, and envs. Calling init or init_with more than once overwrites, unlike env, which appends. The init is one-shot pre-boot.
<Tooltip tip="On microsandbox cloud, only OCI image references are accepted; host-directory and disk-image root filesystems are local-only."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn image(self, image: impl IntoImage) -> Self
Set the root filesystem source. Accepts OCI image names, local directory paths, or disk image paths. The format is auto-detected.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>image</code><span className="msb-type">impl IntoImage</span></div> <div className="msb-param-desc">OCI image name, local directory path, or disk image path.</div> </div> </div><Tooltip tip="On microsandbox cloud, only OCI image references are accepted; host-directory and disk-image root filesystems are local-only."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn image_with(self, f: impl FnOnce(ImageBuilder) -> ImageBuilder) -> Self
use microsandbox::size::SizeExt;
let sb = Sandbox::builder("worker")
.image_with(|i| i.oci("python:3.12").upper_size(8.gib()))
.create()
.await?;
Configure an explicit rootfs source. Use this for OCI-only settings such as the writable overlay upper size, or for disk images when the filesystem type can't be auto-detected.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>f</code><span className="msb-type">FnOnce(ImageBuilder)</span></div> <div className="msb-param-desc">Configure the rootfs source.</div> </div> </div>fn log_level(self, level: LogLevel) -> Self
Override the sandbox process's log verbosity.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>level</code><a className="msb-type" href="#loglevel">LogLevel</a></div> <div className="msb-param-desc">Log level.</div> </div> </div>fn max_duration(self, secs: u64) -> Self
Set the maximum sandbox lifetime in seconds. When exceeded, the sandbox is drained and stopped. Enforced on the host side - the guest cannot override it.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>secs</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Maximum lifetime in seconds.</div> </div> </div>fn memory(self, size: impl Into<Mebibytes>) -> Self
Set the guest memory size. Physical pages are only allocated as the guest touches them, so this is a limit, not an upfront reservation. Default: 512 MiB.
<Tooltip tip="On microsandbox cloud these ceilings are not carried; the maximum is pinned to the initial value. Recreate the sandbox to resize."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn max_memory(self, size: impl Into<Mebibytes>) -> Self
Set the boot-time maximum hotpluggable guest memory. This reserves the envelope a sandbox can use after restart-backed changes and future live memory activation; it does not increase the effective memory by itself.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>size</code><span className="msb-type">impl Into<Mebibytes></span></div> <div className="msb-param-desc">Maximum memory in MiB.</div> </div> </div>fn thp(self, policy: TransparentHugePagePolicy) -> Self
Select the guest transparent huge-page policy applied through the kernel command line at boot. Default: TransparentHugePagePolicy::Madvise.
fn network(self, f: impl FnOnce(NetworkBuilder) -> NetworkBuilder) -> Self
Configure networking. See Networking for the full builder API.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/networking#networkbuilder">NetworkBuilder</a></div> <div className="msb-param-desc">Configure the network.</div> </div> </div>fn patch(self, f: impl FnOnce(PatchBuilder) -> PatchBuilder) -> Self
Modify the rootfs before the VM boots. Patches go into the writable layer - the base image is untouched. See PatchBuilder for the operations.
<Tooltip tip="Publishing host ports is not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn port(self, host_port: u16, guest_port: u16) -> Self
Publish a TCP port from the sandbox to the host. The default host bind address is 127.0.0.1.
<Tooltip tip="Publishing host ports is not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn port_bind(self, host_bind: IpAddr, host_port: u16, guest_port: u16) -> Self
Publish a TCP port on a specific host bind address, such as 0.0.0.0.
<Tooltip tip="Publishing host ports is not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn port_udp(self, host_port: u16, guest_port: u16) -> Self
Publish a UDP port. The default host bind address is 127.0.0.1.
<Tooltip tip="Publishing host ports is not available on microsandbox cloud."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn port_udp_bind(self, host_bind: IpAddr, host_port: u16, guest_port: u16) -> Self
Publish a UDP port on a specific host bind address.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>host_bind</code><span className="msb-type">IpAddr</span></div> <div className="msb-param-desc">Host bind address.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>host_port</code><span className="msb-type">u16</span></div> <div className="msb-param-desc">Port on the host.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>guest_port</code><span className="msb-type">u16</span></div> <div className="msb-param-desc">Port inside the sandbox.</div> </div> </div>fn pull_policy(self, policy: PullPolicy) -> Self
Control when the OCI image is pulled from the registry.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>policy</code><a className="msb-type" href="#pullpolicy">PullPolicy</a></div> <div className="msb-param-desc">Pull behavior.</div> </div> </div><Tooltip tip="On microsandbox cloud, plain-HTTP and custom-CA registry options are not available; credential auth still works."><span className="msb-badge-limited">Limited on cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn registry(self, f: impl FnOnce(RegistryConfigBuilder) -> RegistryConfigBuilder) -> Self
use microsandbox::{RegistryAuth, Sandbox};
let sb = Sandbox::builder("worker")
.image("registry.example.com/team/app:latest")
.registry(|r| r.auth(RegistryAuth::Basic {
username: "user".into(),
password: "token".into(),
}))
.create()
.await?;
Configure registry connection settings for the sandbox image pull, including explicit auth, insecure HTTP, and custom CA certificates.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#registryconfigbuilder">RegistryConfigBuilder</a></div> <div className="msb-param-desc">Closure that configures registry auth and TLS options.</div> </div> </div><Tooltip tip="Replace-on-create is not available on microsandbox cloud; remove the existing sandbox first."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>
fn replace(self) -> Self
If a sandbox with the same name already exists, stop it, remove it, and create a fresh one. Without this, creation fails on name conflict.
fn script(self, name: impl Into<String>, content: impl Into<String>) -> Self
Add a named script at /.msb/scripts/ inside the guest. Scripts are added to PATH and can be called by name via exec() or shell().
fn secret(self, f: impl FnOnce(SecretBuilder) -> SecretBuilder) -> Self
Add a secret with full configuration. See Secrets for the builder API. Automatically enables TLS interception.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/secrets#secretbuilder">SecretBuilder</a></div> <div className="msb-param-desc">Configure the secret.</div> </div> </div>fn secret_env(self, env_var: impl Into<String>, value: impl Into<String>, allowed_host: impl Into<String>) -> Self
Shorthand for adding a header-injected secret. Equivalent to .secret(|s| s.env(env_var).value(value).allow_host(allowed_host)).
fn shell(self, shell: impl Into<String>) -> Self
Set the shell used by Sandbox::shell(). Default: /bin/sh.
fn user(self, user: impl Into<String>) -> Self
Set the default guest user for all commands.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>user</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">User name or UID.</div> </div> </div>fn volume(self, guest_path: impl Into<String>, f: impl FnOnce(MountBuilder) -> MountBuilder) -> Self
Add a volume mount. See Volumes for mount types.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>guest_path</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Mount point inside the sandbox.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="/sdk/rust/volumes#mountbuilder">MountBuilder</a></div> <div className="msb-param-desc">Configure the mount.</div> </div> </div>fn workdir(self, path: impl Into<String>) -> Self
Set the default working directory for all commands.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div>Builder for pre-boot root filesystem patches.
fn append(self, path: impl Into<String>, content: impl Into<String>) -> Self
Append content to an existing file at path. If the file lives in a lower image layer, it's copied up first.
<Tooltip tip="On microsandbox cloud, host sources resolve against your organization's host volume, not the computer running the SDK or CLI."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn copy_dir(self, src: impl Into<PathBuf>, dst: impl Into<String>, replace: bool) -> Self
Recursively copy a host directory at src into the guest rootfs at dst.
<Tooltip tip="On microsandbox cloud, host sources resolve against your organization's host volume, not the computer running the SDK or CLI."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn copy_file(
self,
src: impl Into<PathBuf>,
dst: impl Into<String>,
mode: Option<u32>,
replace: bool,
) -> Self
Copy a single host file at src into the guest rootfs at dst.
fn file(
self,
path: impl Into<String>,
content: impl Into<Vec<u8>>,
mode: Option<u32>,
replace: bool,
) -> Self
Write raw bytes at path.
<Tooltip tip="On microsandbox cloud, host sources resolve against your organization's host volume, not the computer running the SDK or CLI."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn mkdir(self, path: impl Into<String>, mode: Option<u32>) -> Self
Create a directory at path. Idempotent: a no-op if the directory already exists.
fn remove(self, path: impl Into<String>) -> Self
Delete a file or directory at path. Idempotent: a no-op if the path doesn't exist.
fn symlink(self, target: impl Into<String>, link: impl Into<String>, replace: bool) -> Self
Create a symlink at link pointing to target.
fn text(
self,
path: impl Into<String>,
content: impl Into<String>,
mode: Option<u32>,
replace: bool,
) -> Self
Write UTF-8 text content at path.
Builder for planning or applying sandbox configuration changes.
async fn apply(self) -> MicrosandboxResult<SandboxModificationPlan>
Apply the changes. Live changes are made to the running sandbox first, and the new config is saved only after they succeed, so a failed apply leaves the old config in place. Changes for a stopped sandbox, or requested with next_start(), are saved and take effect on the next start. With restart(), the sandbox is stopped and started so that restart-required changes take effect.
A live CPU or memory resize can take a moment to settle. The returned plan's resize_status reports progress per resource; see ResourceResizeStatus.
fn cpus(self, cpus: u8) -> Self
Set the desired effective vCPU count. Applies live to a running sandbox when the target fits inside the booted max_cpus; otherwise it requires a restart.
<Tooltip tip="On microsandbox cloud these ceilings are not carried; the maximum is pinned to the initial value. Recreate the sandbox to resize."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn max_cpus(self, max_cpus: u8) -> Self
Set the desired boot-time maximum possible vCPU count. Capacity is fixed at boot, so this is always restart-backed on a running sandbox.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>max_cpus</code><span className="msb-type">u8</span></div> <div className="msb-param-desc">Maximum possible vCPUs.</div> </div> </div>async fn dry_run(self) -> MicrosandboxResult<SandboxModificationPlan>
let plan = sb.modify().cpus(8).dry_run().await?;
for change in &plan.changes {
if let PlannedChange::Config(c) = change {
println!("{}: {:?} -> {:?} ({:?})", c.field, c.before, c.after, c.disposition);
}
}
Compute the modification plan without applying anything. Use it to preview how each change classifies and whether conflicts block the patch.
<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#sandboxmodificationplan">SandboxModificationPlan</a></div> <div className="msb-param-desc">The plan, with <code>applied: false</code>.</div> </div> </div>fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self
Set an environment variable for future execs. Can be called multiple times. On a running sandbox this applies to future execs only; running processes keep their current environment.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Variable name.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Variable value.</div> </div> </div>fn remove_env(self, key: impl Into<String>) -> Self
Remove an environment variable. Same future-execs-only semantics as env().
fn label(self, key: impl Into<String>, value: impl Into<String>) -> Self
Set a sandbox label. Can be called multiple times.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Label key.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Label value.</div> </div> </div>fn remove_label(self, key: impl Into<String>) -> Self
Remove a sandbox label.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Label key to remove.</div> </div> </div>fn memory(self, size: impl Into<Mebibytes>) -> Self
Set the desired effective guest memory. Applies live to a running sandbox when the target fits inside the booted max_memory; otherwise it requires a restart.
fn memory_mib(self, memory_mib: u32) -> Self
Set the desired effective guest memory in MiB. Same as memory() with an explicit unit.
<Tooltip tip="On microsandbox cloud these ceilings are not carried; the maximum is pinned to the initial value. Recreate the sandbox to resize."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn max_memory(self, size: impl Into<Mebibytes>) -> Self
Set the desired boot-time maximum hotpluggable memory. Capacity is fixed at boot, so this is always restart-backed on a running sandbox.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>size</code><span className="msb-type">impl Into<Mebibytes></span></div> <div className="msb-param-desc">Maximum memory in MiB.</div> </div> </div><Tooltip tip="On microsandbox cloud these ceilings are not carried; the maximum is pinned to the initial value. Recreate the sandbox to resize."><span className="msb-badge-note">On cloud <Icon icon="circle-info" size={11} /></span></Tooltip>
fn max_memory_mib(self, max_memory_mib: u32) -> Self
Set the desired boot-time maximum hotpluggable memory in MiB. Same as max_memory() with an explicit unit.
fn next_start(self) -> Self
Persist the requested changes for the next start, leaving any running VM unchanged. Every change classifies as next start.
fn restart(self) -> Self
Plan under restart-backed apply semantics. When the patch contains restart-required changes, apply() stops the sandbox, persists the config, and starts it again so the changes become active now.
fn secret(self, f: impl FnOnce(SecretPatchBuilder) -> SecretPatchBuilder) -> Self
use microsandbox::sandbox::SecretSource;
let plan = sb.modify()
.secret(|s| s
.env("API_KEY")
.source(SecretSource::Env { var: "API_KEY".into() })
.allow_host("api.example.com"))
.apply()
.await?;
Declare the desired state of one secret via a SecretPatchBuilder closure. The spec mirrors the create-time SecretBuilder vocabulary, and the planner diffs it against the existing config to infer the change: a secret that does not exist yet is added, material on an existing secret rotated, and host or placeholder differences update those aspects. Declaring the same secret again replaces the earlier spec; removal is always explicit through remove_secret().
fn remove_secret(self, name: impl Into<String>) -> Self
Remove a secret. Removal is always explicit; omitting a secret from the patch never removes it.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Secret name (its environment variable name).</div> </div> </div>fn workdir(self, path: impl Into<String>) -> Self
Set the working directory for future execs. On a running sandbox this applies to future execs only.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div>Builder passed to registry() for per-sandbox registry connection settings.
auth(auth: RegistryAuth)
Set explicit credentials for the image registry
insecure()
Use plain HTTP for the registry
ca_certs(pem_data: Vec<u8>)
Trust additional PEM-encoded CA certificates
Fluent configuration passed to Sandbox::list_with(). Keep the labels and limit unchanged when continuing with a cursor.
limit(n)
Set a page size from 1 through 100
cursor(cursor)
Continue after a previous page's next_cursor
label(key, value)
Require one label; repeated calls are AND-matched
labels(iterable)
Add several AND-matched labels
A sandbox metadata and lifecycle handle that does not require an active guest-agent connection.
config()
Parsed configuration
<p className="msb-label">Returns</p>Result<SandboxConfig>
config_json()
Raw JSON configuration
<p className="msb-label">Returns</p>&str
connect()
Connect to a running sandbox; returns an error if it doesn't respond within ten seconds
<p className="msb-label">Returns</p>Result<Sandbox>
connect_with_timeout(timeout)
Same as connect() with an explicit timeout
Result<Sandbox>
created_at()
Creation timestamp
<p className="msb-label">Returns</p>Option<DateTime<Utc>>
kill()
Force terminate and wait until stopped state is observed
<p className="msb-label">Returns</p>Result<()>
kill_with_timeout(timeout)
Same as kill() with an explicit observation timeout
Result<()>
logs()
Read captured exec.log (works without starting)
Result<Vec<LogEntry>>
metrics()
Point-in-time resource metrics
<p className="msb-label">Returns</p>Result<SandboxMetrics>
modify()
Start planning a configuration change (works without starting; changes on a stopped sandbox persist for the next boot)
<p className="msb-label">Returns</p>name()
Sandbox name, up to 128 UTF-8 bytes
<p className="msb-label">Returns</p>&str
ping()
Check agent reachability without refreshing idle activity
<p className="msb-label">Returns</p>Result<SandboxPingResult>
remove()
Delete sandbox and state
<p className="msb-label">Returns</p>Result<()>
request_drain()
Request graceful drain without waiting
<p className="msb-label">Returns</p>Result<()>
request_kill()
Request force termination without waiting
<p className="msb-label">Returns</p>Result<()>
request_stop()
Request graceful shutdown without waiting
<p className="msb-label">Returns</p>Result<()>
start()
Start in attached mode
<p className="msb-label">Returns</p>Result<Sandbox>
start_detached()
Start in detached mode
<p className="msb-label">Returns</p>Result<Sandbox>
status()
Current status
<p className="msb-label">Returns</p>stop()
Gracefully shut down. Waits up to ten seconds for pending writes to flush, then force-kills
<p className="msb-label">Returns</p>Result<()>
stop_with_timeout(timeout)
Same as stop() with an explicit timeout; Duration::ZERO force-kills immediately
Result<()>
touch()
Explicitly refresh the sandbox idle timer
<p className="msb-label">Returns</p>Result<SandboxTouchResult>
updated_at()
Last update timestamp
<p className="msb-label">Returns</p>Option<DateTime<Utc>>
wait_until_stopped()
Block until terminal state is observed
<p className="msb-label">Returns</p>Result<SandboxStopResult>
Builder for one declarative secret change.
fn env(self, name: impl Into<String>) -> Self
Name the secret. This is the environment variable that exposes the placeholder inside the guest. Required.
<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name</code><span className="msb-type">impl Into<String></span></div> <div className="msb-param-desc">Secret name, usually the environment variable name.</div> </div> </div>fn source(self, source: SecretSource) -> Self
Provide the secret material as a host-side SecretSource reference. The durable config records only the reference, and the value is resolved host-side when the change applies. Mutually exclusive with value(...).
fn value(self, value: impl Into<String>) -> Self
Provide the secret material as a raw value, for embedders that hold only a value. The value is zeroized on drop, redacted from Debug, and never enters the plan. Applying a value persists it into the durable config until a later source-based rotate migrates it to a reference, the same at-rest property as secret_env(). Mutually exclusive with source(...).
fn placeholder(self, placeholder: impl Into<String>) -> Self
Set the guest-visible placeholder. Placeholder changes cannot reach already-running processes, so they classify as requires restart on a running sandbox.
fn allow_host(self, host: impl Into<String>) -> Self
Add an allowed host pattern, such as api.example.com, *.example.org, or *. A non-empty list replaces the secret's current allow-list; an empty list leaves it unchanged. A new secret needs at least one.
A single captured log entry returned by logs().
| Field | Type | Description |
|---|---|---|
| timestamp | DateTime<Utc> | Wall-clock capture time on the host |
| source | LogSource | Where the chunk came from |
| session_id | Option<u64> | Relay-monotonic session id; None for System entries |
| data | Bytes | The chunk's bytes (UTF-8 lossy decoded by default; raw bytes if --raw mode was used) |
Sandbox process log verbosity.
| Value | Description |
|---|---|
Error | Errors only |
Warn | Warnings and errors only |
Info | Info and higher |
Debug | Debug and higher |
Trace | Most verbose - all diagnostic output |
Filters passed to logs(). All fields optional. LogOptions::default() returns everything for the default sources (Stdout + Stderr + Output).
| Field | Type | Description |
|---|---|---|
| tail | Option<usize> | Show only the last N entries after other filters apply |
| since | Option<DateTime<Utc>> | Inclusive lower bound on entry timestamp |
| until | Option<DateTime<Utc>> | Exclusive upper bound on entry timestamp |
| sources | Vec<LogSource> | Sources to include. Empty = [Stdout, Stderr, Output] (the default user-program sources). Add System to merge runtime/kernel diagnostics. |
Tag indicating where a captured log entry came from.
| Value | Description |
|---|---|
Stdout | Captured from a session's stdout (pipe mode; streams stayed separated) |
Stderr | Captured from a session's stderr (pipe mode) |
Output | Captured from a session running in pty mode. PTY allocation merges stdout and stderr at the kernel level inside the guest, so they arrive as a single stream, tagged Output rather than mislabeled as Stdout. |
System | Synthetic entry: lifecycle markers in exec.log plus runtime/kernel diagnostic lines merged in at read time when System is requested. |
Result of a successful agent reachability check.
| Field | Type | Description |
|---|---|---|
| name | String | Sandbox name that was pinged |
| latency | Duration | SDK-measured round-trip latency |
Result of an explicit idle-timer refresh.
| Field | Type | Description |
|---|---|---|
| name | String | Sandbox name that was touched |
| activity_seq | u64 | Agent activity sequence after the touch was recorded |
Controls when the SDK fetches an OCI image from the registry.
| Value | Description |
|---|---|
Always | Pull the image every time, even if cached locally |
IfMissing | Pull only if the image is not already cached. This is the default. |
Never | Never pull; fail if the image is not cached locally |
Credentials for authenticating to a private container registry.
| Variant | Fields | Description |
|---|---|---|
Basic | - username: String |
password: String | Username and password authentication |The full configuration of a sandbox. Obtained via config() or built via SandboxBuilder. Contains all settings used to create the sandbox.
| Field | Type | Description |
|---|---|---|
| cpus | u8 | Number of virtual CPUs |
| env | Vec<(String, String)> | Environment variables |
| idle_timeout_secs | Option<u64> | Idle timeout |
| image | RootfsSource | Root filesystem source (OCI, bind, or disk image) |
| max_duration_secs | Option<u64> | Maximum lifetime |
| max_cpus | u8 | Boot-time maximum possible virtual CPUs |
| max_memory_mib | u32 | Boot-time maximum hotpluggable memory in MiB |
| memory_mib | u32 | Guest memory in MiB |
| name | String | Sandbox name, up to 128 UTF-8 bytes |
| patches | Vec<Patch> | Rootfs patches |
| scripts | Vec<(String, String)> | Named scripts |
| shell | Option<String> | Shell for shell() calls |
| volumes | Vec<VolumeMount> | Volume mounts |
| workdir | Option<String> | Default working directory |
One stable, newest-first page returned by Sandbox::list() or Sandbox::list_with().
| Field | Type | Description |
|---|---|---|
sandboxes | Vec<SandboxHandle> | Handles in this page |
next_cursor | Option<String> | Opaque continuation cursor, or None on the final page |
Dry-run or apply plan for a sandbox modification. Values never appear in a plan: secret entries carry only guest-visible references.
| Field | Type | Description |
|---|---|---|
| sandbox | String | Sandbox being modified |
| status | String | Sandbox status used for classification ("running", "stopped", ...) |
| applied | bool | Whether the changes were applied; false for dry runs |
| policy | ModificationPolicy | Policy used to produce the plan: NoRestart (default), NextStart, or Restart |
| changes | Vec<PlannedChange> | Planned changes, one entry per field or secret |
| conflicts | Vec<ModificationConflict> | Conflicts (field + message) that must be resolved before the patch can apply |
| warnings | Vec<ModificationWarning> | Non-fatal warnings (field + message) about the patch or current runtime capabilities, e.g. the future-execs-only env caveat |
| resize_status | Vec<ResourceResizeStatus> | Live resource resize outcomes, populated by apply() when a live change ran |
Host-side source for secret material. The source is resolved when the modification applies, and plans only show guest-visible references.
Import path: microsandbox::sandbox::SecretSource.
| Variant | Field | Description |
|---|---|---|
Env | var: String | Read the value from a host environment variable at apply time |
Store | reference: String | Reserved for a host-side secret store reference; current modifiers report it as unsupported |
One planned modification entry. This enum has a Config variant for ordinary configuration fields and a Secret variant for secret changes.
| Variant | Type | Description |
|---|---|---|
Config | ConfigPlannedChange | Ordinary config change |
Secret | SecretPlannedChange | Secret change. Values are omitted by construction; references are guest-visible only |
Ordinary configuration change in a modification plan.
| Field | Type | Description |
|---|---|---|
| field | String | Config field being changed |
| change | ChangeKind | Added, Updated, or Removed |
| before | Option<String> | Previous safe visible state |
| after | Option<String> | New safe visible state |
| disposition | ModificationDisposition | When or whether the change can take effect |
| reason | Option<String> | Human-readable reason for the classification, when useful |
Secret change in a modification plan. Values are omitted by construction; before_ref and after_ref are guest-visible references.
| Field | Type | Description |
|---|---|---|
| field | String | Always "secret" |
| name | String | Stable secret identity, usually the environment variable name |
| change | SecretChangeKind | Added, Rotated, Removed, Renamed, HostsUpdated, or PlaceholderUpdated |
| before_ref | Option<String> | Previous guest-visible reference or placeholder |
| after_ref | Option<String> | New guest-visible reference or placeholder |
| disposition | ModificationDisposition | When or whether the change can take effect |
| allow_hosts | Vec<String> | Allowed hosts after the requested change |
| reason | Option<String> | Human-readable reason for the classification, when useful |
When or whether a planned change can take effect. Serializes as the quoted strings below.
| Value | Description |
|---|---|
Live ("live") | Applies to the running VM now |
NextStart ("next start") | Persists to the desired config and applies the next time the sandbox starts |
RequiresRestart ("requires restart") | Needs a restart before it can take effect; apply() refuses it unless the restart() policy is selected |
Unsupported ("unsupported") | Cannot be changed by modify |
Runtime convergence status for a live resource resize. Enforcement applies immediately; the guest converges asynchronously (onlining CPUs, plugging memory blocks).
| Field | Type | Description |
|---|---|---|
| resource | ResourceKind | Cpus or Memory |
| requested | String | Requested value |
| actual | String | Actual value observed in the guest/runtime |
| enforced | String | Host/VMM-enforced value |
| state | ResourceConvergenceState | Convergence state, see below |
| State | Description |
|---|---|
Accepted | The runtime accepted the request |
Converging | The guest and VMM are still converging on the requested state |
Applied | Desired, actual, and enforced state match |
GuestRefused | The guest would not cooperate; the host enforces the new limit anyway |
Failed | The resize failed |
Observed terminal sandbox state returned by wait_until_stopped().
| Field | Type | Description |
|---|---|---|
| name | String | Sandbox name |
| status | SandboxStatus | Terminal status that was observed |
| exit_code | Option<i32> | Process exit code when available from an owned child process |
| signal | Option<i32> | Terminating signal when available from an owned child process |
| observed_at | DateTime<Utc> | When the terminal state was observed |
| source | Option<String> | Description of the observation source |
Point-in-time resource usage snapshot.
| Field | Type | Description |
|---|---|---|
| cpu_percent | f32 | CPU usage as a percentage |
| disk_read_bytes | u64 | Total bytes read from disk since boot |
| disk_write_bytes | u64 | Total bytes written to disk since boot |
| memory_bytes | u64 | Current memory usage in bytes |
| memory_limit_bytes | u64 | Memory limit in bytes |
| net_rx_bytes | u64 | Total bytes received over the network since boot |
| net_tx_bytes | u64 | Total bytes sent over the network since boot |
| upper_used_bytes | Option<u64> | Guest-visible OCI upper filesystem used bytes when the protected reporter is available and fresh |
| upper_free_bytes | Option<u64> | Guest-visible OCI upper filesystem free bytes when the protected reporter is available and fresh |
| upper_host_allocated_bytes | Option<u64> | Host-allocated bytes for the writable OCI upper image when available |
| timestamp | DateTime<Utc> | When this measurement was taken |
| uptime | Duration | Time since the sandbox was created |
| Value | Description |
|---|---|
Crashed | VM exited unexpectedly (kernel panic, OOM, etc.) |
Draining | Graceful shutdown in progress; existing commands finish, new ones rejected |
Running | Guest agent is ready; exec, shell, fs work |
Stopped | VM shut down; configuration persisted; can be restarted |