Back to Microsandbox

Snapshots

docs/sdk/rust/snapshots.mdx

0.5.1046.3 KB
Original Source

Capture a stopped sandbox's writable upper layer into a self-describing, content-addressed artifact on disk, then list, verify, export, import, or boot a fresh sandbox from it. See Snapshots for concepts and walkthroughs; this page is the Rust SDK reference.

<div className="msb-glance"> <p className="msb-gl"><span className="msb-dot static"></span>Static · Snapshot<span className="msb-ct">10</span></p> <a className="msb-row" href="#snapshotbuilder"><span className="msb-rn">Snapshot::builder()</span><span className="msb-rg">configure a new snapshot</span></a> <a className="msb-row" href="#snapshotcreate"><span className="msb-rn">Snapshot::create()</span><span className="msb-rg">create from a config</span></a> <a className="msb-row" href="#snapshotopen"><span className="msb-rn">Snapshot::open()</span><span className="msb-rg">open an artifact</span></a> <a className="msb-row" href="#snapshotget"><span className="msb-rn">Snapshot::get()</span><span className="msb-rg">handle from the index</span></a> <a className="msb-row" href="#snapshotlist"><span className="msb-rn">Snapshot::list()</span><span className="msb-rg">indexed snapshots</span></a> <a className="msb-row" href="#snapshotlist_dir"><span className="msb-rn">Snapshot::list_dir()</span><span className="msb-rg">artifacts in a directory</span></a> <a className="msb-row" href="#snapshotremove"><span className="msb-rn">Snapshot::remove()</span><span className="msb-rg">delete an artifact</span></a> <a className="msb-row" href="#snapshotreindex"><span className="msb-rn">Snapshot::reindex()</span><span className="msb-rg">rebuild the index</span></a> <a className="msb-row" href="#snapshotexport"><span className="msb-rn">Snapshot::export()</span><span className="msb-rg">bundle to an archive</span></a> <a className="msb-row" href="#snapshotimport"><span className="msb-rn">Snapshot::import()</span><span className="msb-rg">unpack an archive</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Instance · Snapshot<span className="msb-ct">5</span></p> <a className="msb-row" href="#snap-digest"><span className="msb-rn">snap.digest()</span><span className="msb-rg">content identity</span></a> <a className="msb-row" href="#snap-path"><span className="msb-rn">snap.path()</span><span className="msb-rg">artifact directory</span></a> <a className="msb-row" href="#snap-manifest"><span className="msb-rn">snap.manifest()</span><span className="msb-rg">parsed manifest</span></a> <a className="msb-row" href="#snap-size_bytes"><span className="msb-rn">snap.size_bytes()</span><span className="msb-rg">upper-layer size</span></a> <a className="msb-row" href="#snap-verify"><span className="msb-rn">snap.verify()</span><span className="msb-rg">recheck integrity</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Instance · SnapshotHandle<span className="msb-ct">10</span></p> <a className="msb-row" href="#h-digest"><span className="msb-rn">h.digest()</span><span className="msb-rg">manifest digest</span></a> <a className="msb-row" href="#h-name"><span className="msb-rn">h.name()</span><span className="msb-rg">name alias</span></a> <a className="msb-row" href="#h-parent_digest"><span className="msb-rn">h.parent_digest()</span><span className="msb-rg">parent snapshot</span></a> <a className="msb-row" href="#h-image_ref"><span className="msb-rn">h.image_ref()</span><span className="msb-rg">source image</span></a> <a className="msb-row" href="#h-format"><span className="msb-rn">h.format()</span><span className="msb-rg">upper format</span></a> <a className="msb-row" href="#h-size_bytes"><span className="msb-rn">h.size_bytes()</span><span className="msb-rg">indexed size</span></a> <a className="msb-row" href="#h-created_at"><span className="msb-rn">h.created_at()</span><span className="msb-rg">creation time</span></a> <a className="msb-row" href="#h-path"><span className="msb-rn">h.path()</span><span className="msb-rg">artifact directory</span></a> <a className="msb-row" href="#h-open"><span className="msb-rn">h.open()</span><span className="msb-rg">read the artifact</span></a> <a className="msb-row" href="#h-remove"><span className="msb-rn">h.remove()</span><span className="msb-rg">delete this snapshot</span></a> <p className="msb-gl"><span className="msb-dot static"></span>Sandbox entry points<span className="msb-ct">3</span></p> <a className="msb-row" href="#from_snapshot"><span className="msb-rn">.from_snapshot()</span><span className="msb-rg">boot from a snapshot</span></a> <a className="msb-row" href="#h-snapshot"><span className="msb-rn">h.snapshot()</span><span className="msb-rg">snapshot a stopped sandbox</span></a> <a className="msb-row" href="#h-snapshot_to"><span className="msb-rn">h.snapshot_to()</span><span className="msb-rg">snapshot to a path</span></a> <p className="msb-gl"><span className="msb-dot builder"></span>Builder · SnapshotBuilder<span className="msb-ct">8</span></p> <div className="msb-chiprow"> <a className="msb-chip" href="#destination">.destination()</a> <a className="msb-chip" href="#name">.name()</a> <a className="msb-chip" href="#path">.path()</a> <a className="msb-chip" href="#label">.label()</a> <a className="msb-chip" href="#force">.force()</a> <a className="msb-chip" href="#record_integrity">.record_integrity()</a> <a className="msb-chip" href="#build">.build()</a> <a className="msb-chip" href="#create">.create()</a> </div> <p className="msb-gl"><span className="msb-dot type"></span>Types</p> <div className="msb-chiprow"> <a className="msb-typepill" href="#snapshothandle">SnapshotHandle</a> <a className="msb-typepill" href="#snapshotconfig">SnapshotConfig</a> <a className="msb-typepill" href="#snapshotdestination">SnapshotDestination</a> <a className="msb-typepill" href="#snapshotformat">SnapshotFormat</a> <a className="msb-typepill" href="#exportopts">ExportOpts</a> <a className="msb-typepill" href="#snapshotverifyreport">SnapshotVerifyReport</a> <a className="msb-typepill" href="#upperverifystatus">UpperVerifyStatus</a> <a className="msb-typepill" href="#manifest">Manifest</a> <a className="msb-typepill" href="#imageref">ImageRef</a> <a className="msb-typepill" href="#upperlayer">UpperLayer</a> <a className="msb-typepill" href="#upperintegrity">UpperIntegrity</a> </div> </div> <Note> Snapshots are **local-only** and **disk-only** today: they capture a sandbox that is stopped or crashed, and every operation runs against the default local backend. Cloud snapshots and qcow2 backing chains are deferred. </Note> <p className="msb-label" id="typical-flow">Typical flow</p>
rust
use microsandbox::{Sandbox, Snapshot};

// 1. stop the sandbox you want to capture
let sb = Sandbox::get("api").await?;
sb.stop().await?;

// 2. capture its writable upper layer
let snap = Snapshot::builder("api")
    .name("after-pip-install")     // bare name in the default dir
    .record_integrity()            // hash the upper layer
    .create()
    .await?;
println!("{} ({} bytes)", snap.digest(), snap.size_bytes());

// 3. boot a fresh sandbox from it
let restored = Sandbox::builder("api-restored")
    .from_snapshot("after-pip-install")
    .create()
    .await?;

Static methods


<span className="msb-recv">Snapshot::</span><span className="msb-hn">builder()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span></div>
rust
fn builder(source_sandbox: impl Into<String>) -> SnapshotBuilder

Start configuring a new snapshot of source_sandbox. The builder lets you set the destination, labels, and whether to record content integrity before capturing. See SnapshotBuilder for all options.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>source_sandbox</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Name of the source sandbox. Must be stopped or crashed, and rooted on an OCI image.</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="#snapshotbuilder">SnapshotBuilder</a></div> <div className="msb-param-desc">Builder for configuring the snapshot.</div> </div> </div> <Accordion title="Example">
rust
let snap = Snapshot::builder("api")
    .name("baseline")
    .create()
    .await?;
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">create()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn create(config: SnapshotConfig) -> MicrosandboxResult<Snapshot>

Create a snapshot artifact from a stopped sandbox. Writes manifest.json and the captured upper.ext4 into the destination directory atomically (the manifest is renamed into place last), then best-effort upserts a row into the local index. Index failures are logged but do not fail the call; the artifact is the source of truth. Most callers use the builder's create() instead of constructing a SnapshotConfig by hand.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>config</code><a className="msb-type" href="#snapshotconfig">SnapshotConfig</a></div> <div className="msb-param-desc">Source sandbox, destination, labels, and integrity flag.</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">Snapshot</a></div> <div className="msb-param-desc">The created artifact handle.</div> </div> </div> <Accordion title="Example">
rust
let snap = Snapshot::create(
    Snapshot::builder("api").name("baseline").build()?
).await?;
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">open()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn open(path_or_name: impl AsRef<str>) -> MicrosandboxResult<Snapshot>

Open an existing artifact by path or bare name. Bare names (no path separator, not starting with . or ~) resolve under the default snapshots directory; anything else is treated as a path. This is a fast metadata operation: it verifies the manifest structure, recomputes the manifest digest, and checks that the upper file exists with the recorded size. It does not read the full upper contents; use verify() for that.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">impl AsRef&lt;str&gt;</span></div> <div className="msb-param-desc">Bare snapshot name or filesystem path to an artifact directory.</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">Snapshot</a></div> <div className="msb-param-desc">The opened artifact handle.</div> </div> </div> <Accordion title="Example">
rust
let snap = Snapshot::open("baseline").await?;
println!("{}", snap.manifest().image.reference);
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">get()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn get(name_or_digest: &str) -> MicrosandboxResult<SnapshotHandle>

Look up a lightweight SnapshotHandle in the local index by name, digest (sha256:/sha512: prefix), or path.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name_or_digest</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Snapshot name, manifest digest, or artifact path.</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="#snapshothandle">SnapshotHandle</a></div> <div className="msb-param-desc">Handle backed by the matching index row.</div> </div> </div> <Accordion title="Example">
rust
let h = Snapshot::get("after-pip-install").await?;
println!("{} from {}", h.digest(), h.image_ref());
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">list()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn list() -> MicrosandboxResult<Vec<SnapshotHandle>>

List indexed snapshots from the local DB cache, newest first. External-path artifacts booted by full path aren't in the index and won't appear here; use list_dir to enumerate artifacts on disk directly.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#snapshothandle">Vec&lt;SnapshotHandle&gt;</a></div> <div className="msb-param-desc">Indexed snapshot handles, ordered by creation time descending.</div> </div> </div> <Accordion title="Example">
rust
for h in Snapshot::list().await? {
    println!("{:?} — {}", h.name(), h.digest());
}
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">list_dir()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn list_dir(dir: impl AsRef<Path>) -> MicrosandboxResult<Vec<Snapshot>>

Walk a directory and parse each subdirectory's manifest. Does not touch the index. Skips entries that don't look like snapshot artifacts (no manifest.json) and malformed artifacts.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>dir</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div> <div className="msb-param-desc">Directory to scan for artifacts.</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">Vec&lt;Snapshot&gt;</a></div> <div className="msb-param-desc">One handle per valid artifact found.</div> </div> </div> <Accordion title="Example">
rust
let snaps = Snapshot::list_dir("/data/snapshots").await?;
println!("{} artifacts", snaps.len());
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">remove()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn remove(path_or_name: &str, force: bool) -> MicrosandboxResult<()>

Remove a snapshot artifact (by digest, name, or path) and its index row. Refuses if the snapshot has indexed children unless force is set. The artifact directory is deleted on success and the parent's child count is decremented.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Snapshot digest, name, or artifact path.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>force</code><span className="msb-type">bool</span></div> <div className="msb-param-desc">When <code>true</code>, remove even if the snapshot has indexed children.</div> </div> </div> <Accordion title="Example">
rust
Snapshot::remove("after-pip-install", false).await?;
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">reindex()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn reindex(dir: impl AsRef<Path>) -> MicrosandboxResult<usize>

Rebuild the local index from the artifacts in dir. Upserts an index row for every artifact found, then recomputes parent-edge child counts in one pass so the cache stays honest about the current set of artifacts.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>dir</code><span className="msb-type">impl AsRef&lt;Path&gt;</span></div> <div className="msb-param-desc">Directory of artifacts to index.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">usize</span></div> <div className="msb-param-desc">Number of artifacts indexed.</div> </div> </div> <Accordion title="Example">
rust
let n = Snapshot::reindex("/data/snapshots").await?;
println!("indexed {n} snapshots");
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">export()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn export(name_or_path: &str, out: &Path, opts: ExportOpts) -> MicrosandboxResult<()>

Bundle a snapshot into a .tar.zst archive (or plain .tar) at out. The head snapshot is verified before bundling. The recorded manifest is archived as-is, so create the snapshot with record_integrity() when the archive will cross a trust boundary. See ExportOpts to also include ancestors and the OCI image cache.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>name_or_path</code><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Snapshot name or artifact path to export.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>out</code><span className="msb-type">&amp;Path</span></div> <div className="msb-param-desc">Output archive path. Parent directories are created if missing.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>opts</code><a className="msb-type" href="#exportopts">ExportOpts</a></div> <div className="msb-param-desc">Bundling options. <code>ExportOpts::default()</code> writes the head snapshot only, zstd-compressed.</div> </div> </div> <Accordion title="Example">
rust
use microsandbox::snapshot::ExportOpts;
use std::path::Path;

Snapshot::export(
    "baseline",
    Path::new("/tmp/baseline.tar.zst"),
    ExportOpts { with_parents: true, with_image: true, ..Default::default() },
).await?;
</Accordion>

<span className="msb-recv">Snapshot::</span><span className="msb-hn">import()</span>

<div className="msb-tags"><span className="msb-tag is-static">static</span><span className="msb-tag is-async">async</span></div>
rust
async fn import(archive_path: &Path, dest: Option<&Path>) -> MicrosandboxResult<SnapshotHandle>

Unpack a snapshot archive (.tar.zst or .tar, detected from magic bytes) into the snapshots directory (or dest), routing any bundled image-cache entries into the global cache and registering everything found in the index. Recorded integrity is verified as artifacts land. Returns a handle for the head snapshot.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>archive_path</code><span className="msb-type">&amp;Path</span></div> <div className="msb-param-desc">Archive to unpack.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>dest</code><span className="msb-type">Option&lt;&amp;Path&gt;</span></div> <div className="msb-param-desc">Destination directory. <code>None</code> uses the default snapshots directory.</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="#snapshothandle">SnapshotHandle</a></div> <div className="msb-param-desc">Handle for the head (last-listed) snapshot.</div> </div> </div> <Accordion title="Example">
rust
use std::path::Path;

let h = Snapshot::import(Path::new("/tmp/baseline.tar.zst"), None).await?;
println!("imported {}", h.digest());
</Accordion>

Instance methods

Methods on an opened Snapshot artifact.


<span className="msb-recv">snap.</span><span className="msb-hn">digest()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn digest(&self) -> &str

Canonical content digest of this snapshot's manifest (sha256:hex). This is the snapshot's identity.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">&amp;str</span></div> <div className="msb-param-desc">Manifest digest in <code>sha256:hex</code> form.</div> </div> </div>

<span className="msb-recv">snap.</span><span className="msb-hn">path()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn path(&self) -> &Path

Path to the artifact directory holding the canonical manifest.json and the captured upper file.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">&amp;Path</span></div> <div className="msb-param-desc">Artifact directory path.</div> </div> </div>

<span className="msb-recv">snap.</span><span className="msb-hn">manifest()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn manifest(&self) -> &Manifest

The parsed Manifest: schema, format, fstype, image reference, parent, creation time, labels, and upper-layer metadata.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#manifest">&amp;Manifest</a></div> <div className="msb-param-desc">Parsed snapshot manifest.</div> </div> </div> <Accordion title="Example">
rust
let snap = Snapshot::open("baseline").await?;
let m = snap.manifest();
println!("{} @ {}", m.image.reference, m.image.manifest_digest);
</Accordion>

<span className="msb-recv">snap.</span><span className="msb-hn">size_bytes()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn size_bytes(&self) -> u64

Apparent size of the captured upper layer in bytes (the ext4 virtual size; sparse on disk).

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">u64</span></div> <div className="msb-param-desc">Upper-layer apparent size in bytes.</div> </div> </div>

<span className="msb-recv">snap.</span><span className="msb-hn">verify()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn verify(&self) -> MicrosandboxResult<SnapshotVerifyReport>

Recompute the upper layer's content hash and compare it against the manifest. Walks data extents only, so a multi-GiB sparse file with a little data verifies in milliseconds. Returns NotRecorded when the manifest has no integrity descriptor; errors with SnapshotIntegrity on mismatch.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#snapshotverifyreport">SnapshotVerifyReport</a></div> <div className="msb-param-desc">Digest, path, and upper-layer verification status.</div> </div> </div> <Accordion title="Example">
rust
use microsandbox::snapshot::UpperVerifyStatus;

let snap = Snapshot::open("baseline").await?;
match snap.verify().await?.upper {
    UpperVerifyStatus::Verified { algorithm, .. } => println!("ok via {algorithm}"),
    UpperVerifyStatus::NotRecorded => println!("no integrity hash recorded"),
}
</Accordion>

SnapshotHandle methods

Accessors and lifecycle on a SnapshotHandle (an index row). Returned by Snapshot::get(), Snapshot::list(), and Snapshot::import().


<span className="msb-recv">h.</span><span className="msb-hn">digest()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn digest(&self) -> &str

Manifest digest (sha256:hex), the canonical identity.


<span className="msb-recv">h.</span><span className="msb-hn">name()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn name(&self) -> Option<&str>

Name alias, or None for digest-only entries.


<span className="msb-recv">h.</span><span className="msb-hn">parent_digest()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn parent_digest(&self) -> Option<&str>

The parent snapshot's digest, or None for a root. Always None today; populated once chained snapshots land.


<span className="msb-recv">h.</span><span className="msb-hn">image_ref()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn image_ref(&self) -> &str

Image reference the snapshot was taken from.


<span className="msb-recv">h.</span><span className="msb-hn">format()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn format(&self) -> SnapshotFormat

On-disk format of the upper layer.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#snapshotformat">SnapshotFormat</a></div> <div className="msb-param-desc">Upper-layer format (<code>Raw</code> today).</div> </div> </div>

<span className="msb-recv">h.</span><span className="msb-hn">size_bytes()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn size_bytes(&self) -> Option<u64>

Apparent size of the upper file at index time, if recorded.


<span className="msb-recv">h.</span><span className="msb-hn">created_at()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn created_at(&self) -> chrono::NaiveDateTime

Snapshot creation time, parsed from the manifest.


<span className="msb-recv">h.</span><span className="msb-hn">path()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span></div>
rust
fn path(&self) -> &Path

Local artifact directory path.


<span className="msb-recv">h.</span><span className="msb-hn">open()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn open(&self) -> MicrosandboxResult<Snapshot>

Open the underlying artifact metadata, upgrading this lightweight handle to a full Snapshot. Equivalent to Snapshot::open(self.path()).

<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">Snapshot</a></div> <div className="msb-param-desc">The opened artifact.</div> </div> </div> <Accordion title="Example">
rust
let h = Snapshot::get("baseline").await?;
let snap = h.open().await?;
snap.verify().await?;
</Accordion>

<span className="msb-recv">h.</span><span className="msb-hn">remove()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn remove(&self, force: bool) -> MicrosandboxResult<()>

Remove this snapshot. Delegates to Snapshot::remove(self.digest(), force).

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>force</code><span className="msb-type">bool</span></div> <div className="msb-param-desc">When <code>true</code>, remove even if the snapshot has indexed children.</div> </div> </div> <Accordion title="Example">
rust
let h = Snapshot::get("baseline").await?;
h.remove(false).await?;
</Accordion>

Sandbox entry points

Snapshot-related methods that live on the sandbox builder and handle. See Sandbox for the full sandbox API.


<span className="msb-recv">.</span><span className="msb-hn">from_snapshot()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn from_snapshot(self, path_or_name: impl Into<String>) -> Self

SandboxBuilder setter. Boot a fresh sandbox from a snapshot artifact. The snapshot already pins the image reference and digest, so this is mutually exclusive with image() and image_with(). The artifact is opened and its integrity verified at create() time, not here.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>path_or_name</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Bare name resolved under the default snapshots directory, or a path to an artifact directory.</div> </div> </div> <Accordion title="Example">
rust
let sb = Sandbox::builder("api-restored")
    .from_snapshot("after-pip-install")
    .create()
    .await?;
</Accordion>

<span className="msb-recv">h.</span><span className="msb-hn">snapshot()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn snapshot(&self, name: &str) -> MicrosandboxResult<Snapshot>

SandboxHandle method. Snapshot this sandbox under a bare name in the default snapshots directory (~/.microsandbox/snapshots/<name>/). The sandbox must be stopped or crashed; running sandboxes are rejected with SnapshotSandboxRunning. Local handles only. For an explicit destination see snapshot_to().

<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">&amp;str</span></div> <div className="msb-param-desc">Bare snapshot name.</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">Snapshot</a></div> <div className="msb-param-desc">The created artifact handle.</div> </div> </div> <Accordion title="Example">
rust
let h = Sandbox::get("api").await?;
h.stop().await?;
let snap = h.snapshot("baseline").await?;
</Accordion>

<span className="msb-recv">h.</span><span className="msb-hn">snapshot_to()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn snapshot_to(&self, path: impl AsRef<Path>) -> MicrosandboxResult<Snapshot>

SandboxHandle method. Snapshot this sandbox to an explicit filesystem path. The sandbox must be stopped or crashed. Local handles only. For the common case of writing under the default snapshots directory see snapshot().

<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 AsRef&lt;Path&gt;</span></div> <div className="msb-param-desc">Destination artifact directory.</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">Snapshot</a></div> <div className="msb-param-desc">The created artifact handle.</div> </div> </div> <Accordion title="Example">
rust
let h = Sandbox::get("api").await?;
h.stop().await?;
let snap = h.snapshot_to("/data/snapshots/baseline").await?;
</Accordion>

SnapshotBuilder

Builder for a SnapshotConfig. Obtained via Snapshot::builder(source_sandbox). A destination is required (name or path); the other setters are optional. Every setter returns Self, so calls chain.

rust
let snap = Snapshot::builder("api")
    .name("after-pip-install")     // bare name in default dir
    .label("stage", "post-deps")
    .force()                       // overwrite if it exists
    .record_integrity()            // hash the upper layer
    .create()
    .await?;

<span className="msb-recv">.</span><span className="msb-hn">destination()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn destination(self, dest: SnapshotDestination) -> Self

Set the artifact destination explicitly. The name and path setters are convenience wrappers over this.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>dest</code><a className="msb-type" href="#snapshotdestination">SnapshotDestination</a></div> <div className="msb-param-desc">Name- or path-based destination.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">name()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn name(self, name: impl Into<String>) -> Self

Convenience: use a bare name resolved under the default snapshots directory. Sets the destination to SnapshotDestination::Name.

<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&lt;String&gt;</span></div> <div className="msb-param-desc">Bare snapshot name. Must not be empty, contain <code>/</code>, or start with <code>.</code>.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">path()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn path(self, path: impl Into<PathBuf>) -> Self

Convenience: write the artifact to an explicit path. Sets the destination to SnapshotDestination::Path.

<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&lt;PathBuf&gt;</span></div> <div className="msb-param-desc">Destination artifact directory.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">label()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn label(self, key: impl Into<String>, value: impl Into<String>) -> Self

Add a user label. Can be called multiple times. Labels are sorted by key in the manifest's canonical form.

<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&lt;String&gt;</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&lt;String&gt;</span></div> <div className="msb-param-desc">Label value.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">force()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn force(self) -> Self

Overwrite an existing artifact at the destination. Without this, creation fails with SnapshotAlreadyExists if the destination directory exists.


<span className="msb-recv">.</span><span className="msb-hn">record_integrity()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn record_integrity(self) -> Self

Compute and record an upper-layer content-integrity hash during creation. Recorded integrity is what verify() checks and what import/export rely on when crossing a trust boundary.


<span className="msb-recv">.</span><span className="msb-hn">build()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn build(self) -> MicrosandboxResult<SnapshotConfig>

Materialize the SnapshotConfig without creating the snapshot. Errors with InvalidConfig if no destination was set. For capturing, use create instead; it calls build internally.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#snapshotconfig">SnapshotConfig</a></div> <div className="msb-param-desc">Validated snapshot configuration.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">create()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span><span className="msb-tag is-async">async</span></div>
rust
async fn create(self) -> MicrosandboxResult<Snapshot>

Build and execute the snapshot in one step. Equivalent to Snapshot::create(self.build()?).

<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">Snapshot</a></div> <div className="msb-param-desc">The created artifact handle.</div> </div> </div>

Types

SnapshotHandle

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#snapshotget">Snapshot::get()</a> · <a href="#snapshotlist">Snapshot::list()</a> · <a href="#snapshotimport">Snapshot::import()</a></p>

A lightweight handle backed by a local index row. Use open() to read the artifact metadata, and Snapshot::verify() for explicit content verification. All accessors are listed under SnapshotHandle methods.

MethodTypeDescription
digest()&strManifest digest (sha256:hex)
name()Option<&str>Name alias; None for digest-only entries
parent_digest()Option<&str>Parent snapshot digest, or None for a root
image_ref()&strSource image reference
format()SnapshotFormatOn-disk upper format
size_bytes()Option<u64>Upper file size at index time
created_at()chrono::NaiveDateTimeCreation time from the manifest
path()&PathLocal artifact directory
open()Result<Snapshot>Open the underlying artifact
remove(force)Result<()>Remove this snapshot

SnapshotConfig

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#snapshotcreate">Snapshot::create()</a> · returned by <a href="#build">build()</a></p>

Inputs to create a snapshot. A type alias for SnapshotSpec. Usually built via SnapshotBuilder rather than constructed directly.

FieldTypeDescription
source_sandboxStringName of the source sandbox; must be stopped
destinationSnapshotDestinationWhere to write the artifact
labelsVec<(String, String)>User-supplied labels
forceboolOverwrite an existing artifact at the destination
record_integrityboolCompute and record upper-layer integrity at creation

SnapshotDestination

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Used by <a href="#destination">destination()</a> · <a href="#snapshotconfig">SnapshotConfig.destination</a></p>

Where to place a new snapshot artifact. The builder's name() and path(), and the handle's snapshot() / snapshot_to(), construct this enum internally so callers rarely import it.

VariantFieldsDescription
NameStringBare name resolved under the default snapshots directory
PathPathBufExplicit absolute or relative path to the artifact directory

SnapshotFormat

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Used by <a href="#h-format">format()</a> · <a href="#manifest">Manifest.format</a></p>

On-disk format of the captured upper layer. Today only Raw is produced; the variant exists so qcow2 chains drop in later without a schema migration.

ValueDescription
RawRaw ext4 image, sparse on disk
Qcow2qcow2 with optional backing chain (future)

ExportOpts

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#snapshotexport">Snapshot::export()</a></p>

Options for Snapshot::export(). Implements Default; ExportOpts::default() writes the head snapshot only, zstd-compressed.

FieldTypeDescription
with_parentsboolWalk the parent chain and include each ancestor in the archive
with_imageboolBundle the OCI image artifacts (EROFS layers, fsmeta, VMDK descriptor) from the global cache so the archive boots offline
plain_tarboolSkip zstd compression and write a plain .tar. Default: zstd

SnapshotVerifyReport

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#snap-verify">verify()</a></p>

Result of explicit snapshot verification.

FieldTypeDescription
digestStringSnapshot manifest digest
pathPathBufArtifact directory
upperUpperVerifyStatusUpper-layer content verification result

UpperVerifyStatus

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Used by <a href="#snapshotverifyreport">SnapshotVerifyReport.upper</a></p>

Upper-layer content verification result.

VariantFieldsDescription
NotRecorded-No content integrity descriptor was recorded in the manifest
Verified- algorithm: String
  • digest: String | Recorded integrity matched the computed digest |

Manifest

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#snap-manifest">manifest()</a></p>

The snapshot artifact manifest, the source of truth for an artifact. Re-exported as microsandbox::snapshot::Manifest. Its SHA-256 digest over the canonical byte form is the snapshot's identity. Field order is load-bearing (it determines the canonical byte layout) and must not be reordered.

FieldTypeDescription
schemau32Manifest schema version; readers reject unknown values
formatSnapshotFormatOn-disk format of the upper layer
fstypeStringFilesystem type inside the upper (e.g. ext4)
imageImageRefImage the snapshot was taken from
parentOption<String>Parent snapshot digest, or None for a root
created_atStringRFC 3339 creation timestamp
labelsBTreeMap<String, String>User-supplied labels, sorted by key in canonical form
upperUpperLayerThe captured upper layer
source_sandboxOption<String>Best-effort name of the source sandbox (informational)

ImageRef

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#manifest">Manifest.image</a></p>

Reference to the OCI image the snapshot was taken from. Re-exported as microsandbox::snapshot::ImageRef.

FieldTypeDescription
referenceStringHuman-readable image reference (e.g. docker.io/library/python:3.12)
manifest_digestStringDigest of the OCI manifest, in sha256:hex form

UpperLayer

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#manifest">Manifest.upper</a></p>

Captured upper-layer file metadata. Re-exported as microsandbox::snapshot::UpperLayer.

FieldTypeDescription
fileStringFilename inside the artifact directory (e.g. upper.ext4)
size_bytesu64Apparent size in bytes (ext4 virtual size; sparse on disk)
integrityOption<UpperIntegrity>Optional content integrity descriptor; None on local hot paths

UpperIntegrity

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Used by <a href="#upperlayer">UpperLayer.integrity</a></p>

Content integrity descriptor for the captured upper layer.

FieldTypeDescription
algorithmStringDigest algorithm name (e.g. msb-sparse-sha256-v1)
digestStringAlgorithm output, in sha256:hex form for current algorithms