pub struct VmConfig { /* private fields */ }Expand description
Configuration for Vm::start. Built via the chainable
VmConfig::with_* methods or constructed directly:
use supermachine::VmConfig;
let cfg = VmConfig::new()
.with_memory_mib(512)
.with_vcpus(2);Implementations§
Source§impl VmConfig
impl VmConfig
Sourcepub fn new() -> Self
pub fn new() -> Self
Use the image’s baked defaults for memory + vCPUs;
auto-discover assets; vsock-mux socket in $TMPDIR;
10 s restore timeout.
Sourcepub fn with_memory_mib(self, mib: u32) -> Self
pub fn with_memory_mib(self, mib: u32) -> Self
Override the image’s baked memory.
Sourcepub fn with_vcpus(self, vcpus: u32) -> Self
pub fn with_vcpus(self, vcpus: u32) -> Self
Override the image’s baked vCPU count.
Sourcepub fn with_balloon(self, enable: bool) -> Self
pub fn with_balloon(self, enable: bool) -> Self
Attach a virtio-balloon device so the host can reclaim guest memory via
Vm::request_balloon_inflate (KVM cold boot — Image::start). The
guest needs CONFIG_VIRTIO_BALLOON (the bundled supermachine kernel has
it). Off by default; the warm-pool acquire path ignores it (balloon is
a cold-boot reclaim lever, not snapshotted — matching HVF’s restore default).
Sourcepub fn with_volume(self, spec: VolumeSpec) -> Self
pub fn with_volume(self, spec: VolumeSpec) -> Self
Attach a data volume (KVM): a host-backed virtio-blk mounted in the guest
at spec.guest_path. The backing file is created sparse + formatted ext4
on first use and reused (so data persists across runs); pass the same
host_path to keep state. Multiple volumes become vdb, vdc, … Honored on
the cold-boot start path (snapshots/pools don’t carry volume mounts yet).
let image = Image::from_oci("postgres:16-alpine")?;
let cfg = VmConfig::new()
.with_volume(VolumeSpec::new("/srv/pgdata.img", "/var/lib/postgresql/data"));
let vm = image.start(&cfg)?;Sourcepub fn with_virtiofs(self, spec: MountSpec) -> Self
pub fn with_virtiofs(self, spec: MountSpec) -> Self
Expose a host directory to the guest over virtio-fs (KVM), mounted at
spec.guest_path. Served by an in-process FUSE backend with a DAX window
(the guest init mounts -o dax for zero-copy reads). Mounts survive a
snapshot: the device + FUSE backend tables + DAX slot table are captured
(SMSNAP05) and re-attached on restore (lazy fd reopen + eager DAX rebind).
let image = Image::from_oci("alpine")?;
let cfg = VmConfig::new()
.with_virtiofs(MountSpec::new("/srv/assets", "assets", "/mnt/assets"));
let vm = image.start(&cfg)?;Sourcepub fn with_sentry_pids_max(self, n: u64) -> Self
pub fn with_sentry_pids_max(self, n: u64) -> Self
Cap the sentry guest cell tree’s total processes+threads (cgroup-v2
pids.max) — fork-bomb protection. Sentry backend only. Default is
SENTRY_DEFAULT_PIDS_MAX; the KVM/HVF backends ignore this.
Sourcepub fn with_sentry_uid(self, uid: u32, gid: u32) -> Self
pub fn with_sentry_uid(self, uid: u32, gid: u32) -> Self
Drop the sentry guest cell to (uid, gid), overriding the image’s baked
User. The MULTI-TENANT isolation knob: assign a UNIQUE uid per tenant and
the kernel denies every cross-tenant process_vm / ptrace / signal / same-uid
file access — one tenant’s cell cannot reach another’s. Sentry backend only
(KVM/HVF are hardware-isolated and ignore this). Requires the sentry to run
privileged enough to drop to the uid (it does the confined fs as its own uid;
the guest loses no capability).
Sourcepub fn with_sentry_uncapped(self, uncapped: bool) -> Self
pub fn with_sentry_uncapped(self, uncapped: bool) -> Self
Run the sentry guest cell tree UNCAPPED (no cgroup-v2 memory/CPU/pids caps). Sentry backend only; the syscall wall + page-table isolation still apply. Off by default — leave it off in production so a single tenant can’t exhaust the host. Use it only for trusted single-tenant tooling that legitimately needs the whole box.
Sourcepub fn with_sentry_exec_timeout(self, dur: Duration) -> Self
pub fn with_sentry_exec_timeout(self, dur: Duration) -> Self
Bound how long any single sentry exec cell tree may run before the
supervisor SIGKILLs it and reports SentryError::Timeout (exit 137).
Sentry backend only; the KVM/HVF backends ignore it.
The production release-gate knob: left UNSET, the sentry path applies a
generous default ceiling (SENTRY_DEFAULT_EXEC_TIMEOUT, 10 min) in
Image::sentry_sandbox_with, so Vm::start (sentry path) and a
SentryPool are bounded out of the box — a wedged or fork-and-signal-
trapping RUN can’t hang the caller forever — while a long but legitimate
install/build still completes. Pass a tighter dur for snappier SLAs, or
Duration::ZERO to run UNLIMITED (trusted single-tenant tooling).
Sourcepub fn with_for_build(self, on: bool) -> Self
pub fn with_for_build(self, on: bool) -> Self
Mark this config as backing a Dockerfile BUILD stage (sentry backend only).
true makes a [SentryPool] serve the stage from a per-build private
reflink clone of the warm rootfs (per-build/per-stage filesystem isolation +
failed-RUN rollback) and suppresses the base image’s baked-workload
auto-start. Set by the builder’s build-pool chains via
PoolBuilder::for_build; the KVM/HVF backends ignore it. Off by default.
Sourcepub fn with_assets(self, assets: AssetPaths) -> Self
pub fn with_assets(self, assets: AssetPaths) -> Self
Override asset auto-discovery. Useful for .app bundles
that ship the kernel + init shim under
Contents/Resources/.
Sourcepub fn with_vsock_mux_dir(self, dir: impl Into<PathBuf>) -> Self
pub fn with_vsock_mux_dir(self, dir: impl Into<PathBuf>) -> Self
Where to put the host-side vsock-mux unix socket. Default
is $TMPDIR. Use this if you need the socket inside an
app-private dir for sandboxing reasons.
Sourcepub fn with_restore_timeout(self, timeout: Duration) -> Self
pub fn with_restore_timeout(self, timeout: Duration) -> Self
How long to wait for the snapshot to restore. Default 10 s.