Back to Microsandbox

Global config

docs/configuration.mdx

0.6.916.2 KB
Original Source

microsandbox reads its global configuration from ~/.microsandbox/config.json. All fields are optional. A missing file or empty JSON object is equivalent to using the defaults.

<Accordion title="Full example"> ```json { "home": "/custom/path/.microsandbox", "log_level": "info", "deployment_profile": "multi-tenant", "database": { "url": "sqlite:///tmp/msb.db", "max_connections": 10, "connect_timeout_secs": 30, "busy_timeout_secs": 30 }, "paths": { "msb": "/usr/local/bin/msb", "libkrunfw": "/usr/local/lib/libkrunfw.so", "cache": "/mnt/fast/msb-cache", "sandboxes": null, "volumes": null, "snapshots": null, "logs": null, "secrets": null }, "sandbox_defaults": { "cpus": 2, "memory_mib": 1024, "cpu_placement": "auto", "placement_profile": "latency", "thp": "madvise", "oci": { "root_disk": { "kind": "flat", "size_mib": 8192, "clone": "auto" } }, "shell": "/bin/bash", "workdir": "/app" }, "runtime": { "placement_profiles": { "latency": { "numa": { "mode": "prefer_single" }, "memory": { "mode": "follow_cpu" } } }, "block_writeback": { "mode": "auto" } }, "registries": { "ca_certs": "/path/to/corporate-ca.pem", "hosts": { "ghcr.io": { "auth": { "username": "octocat", "store": "keyring" } }, "registry.example.com": { "insecure": true, "auth": { "username": "deploy", "password_env": "REGISTRY_TOKEN" } }, "docker.io": { "auth": { "username": "user", "secret_name": "dockerhub-token" } } } }, "metrics": { "capacity": 4096 }, "active_profile": "prod", "profiles": { "prod": { "backend": "cloud", "api_key_ref": "env:MSB_API_KEY" }, "local": { "backend": "local" } } } ``` </Accordion>

Top-level fields

FieldDefaultDescription
home~/.microsandboxRoot directory for all microsandbox data
log_levelnull (silent)Log level for sandbox processes: error, warn, info, debug, trace
deployment_profilenullAuthoritative local host-runtime isolation profile: single-tenant or multi-tenant
databasereferenceDatabase connection settings
pathsreferencePath overrides for binaries and directories
sandbox_defaultsreferenceDefaults applied to local sandboxes
runtimereferenceHost runtime performance policy
registriesreferenceContainer registry authentication
metricsreferenceLive metrics shared-memory registry settings
active_profilenullDefault backend profile name
profilesreferenceNamed backend profiles

deployment_profile

Set deployment_profile when the local host must enforce one deployment policy for every sandbox:

json
{
  "deployment_profile": "multi-tenant"
}

single-tenant preserves the network configuration requested by each sandbox. multi-tenant applies the host-runtime isolation floor for shared infrastructure. The configured value is authoritative on create and restart, so a per-sandbox CLI or SDK option cannot weaken or replace it. A programmatic LocalBackendBuilder::deployment_profile() override takes precedence over the file. When the field is absent or null, each sandbox selects its own profile and defaults to single-tenant.

The parser also accepts the internal wire spellings single_tenant and multi_tenant for compatibility, but the kebab-case values above are canonical in this human-edited file. Managed cloud backends ignore this local setting because the hosting platform chooses their effective deployment profile.

database

FieldDefaultDescription
urlnullDatabase URL. Uses SQLite under home when null
max_connections5Maximum connection pool size
connect_timeout_secs30Timeout when acquiring a database connection from the pool
busy_timeout_secs30SQLite busy timeout before a contended write surfaces as an error

paths

All path fields are optional. When null, they resolve relative to home.

On Windows, the default home is %USERPROFILE%\.microsandbox. JSON strings can use escaped backslashes such as "C:\\Users\\you\\.microsandbox\\lib\\libkrunfw.dll" or forward slashes such as "C:/Users/you/.microsandbox/lib/libkrunfw.dll".

FieldDefaultDescription
msb{home}/bin/msbmsb binary. Resolved via: MSB_PATH env, SDK-provided runtime path, this field, debug workspace build paths, default install path, then PATH
libkrunfw{home}/lib/libkrunfwPath to a custom VM kernel (.so on Linux, .dylib on macOS, .dll on Windows). Resolved via: MSB_LIBKRUNFW_PATH env, SDK-provided runtime path, this field, paths next to the resolved msb binary, then default install path
cache{home}/cacheImage layer cache
sandboxes{home}/sandboxesPer-sandbox state
volumes{home}/volumesNamed volumes
snapshots{home}/snapshotsSnapshot artifacts
logs{home}/logsSandbox logs
secrets{home}/secretsSecrets. Registry secrets live under secrets/registries/

Rust SDK path helpers

Rust callers can inspect the active local config and resolve runtime paths with the same precedence used by sandbox startup. microsandbox::config::config() uses the active default backend and returns Unsupported when that backend is cloud.

rust
let cfg = microsandbox::config::config()?;
let msb = cfg.resolve_msb_path()?;
let libkrunfw = cfg.resolve_libkrunfw_path()?;

When your code owns an explicit local backend, prefer the backend-owned config:

rust
use microsandbox::LocalBackend;

let backend = LocalBackend::builder()
    .home("/tmp/msb-home")
    .build()
    .await?;

let cfg = backend.config();
let msb = cfg.resolve_msb_path()?;

LocalBackend has two plain constructors alongside the builder. LocalBackend::lazy() is synchronous and defers opening (and migrating) the local sandbox database until the first operation; it is what backend resolution uses when no backend is set explicitly. LocalBackend::new().await? opens the database up front, so startup fails fast if the database is unusable.

sandbox_defaults

Defaults applied to local sandboxes unless overridden per-sandbox. Cloud backends retain their service-side default policy.

Explicit CLI or SDK options win over config.json, and config.json wins over built-in defaults. Microsandbox resolves the effective values once when it creates a local sandbox and persists that resolved sandbox configuration; changing the global file affects future creations, not existing sandboxes.

For workload effects, host requirements, filesystem expectations, and verification steps for these settings, see Optimization.

FieldDefaultDescription
cpus1Number of vCPUs
memory_mib512Guest memory in MiB
cpu_placement"inherit"Host vCPU placement: inherit, auto, spread, or compact
placement_profilenullName of a host-defined entry in runtime.placement_profiles
thp"madvise"Guest transparent huge-page policy: always, madvise, or never
ocireferenceDefaults for OCI-rooted sandboxes
shell"/bin/sh"Shell for interactive sessions and scripts
workdirnullWorking directory inside the sandbox
metrics_sample_interval_ms1000Runtime metrics sampling interval in milliseconds. Set to 0 to disable sampling.
disable_metrics_samplefalseForce-disable metrics sampling regardless of metrics_sample_interval_ms.

sandbox_defaults.oci

Defaults applied only when the sandbox rootfs is an OCI image.

FieldDefaultDescription
root_disknullDefault OCI root disk using the same tagged shape as the SDK: managed, tmpfs, or flat. A missing value preserves the managed layered root. User-owned disk-image defaults are rejected because they would share one writable image across sandboxes.
upper_size_mibnullDeprecated managed-layered size shorthand. When both this field and root_disk are absent, the resolved managed size is 4096 MiB.

root_disk and upper_size_mib are mutually exclusive. For a portable flat default, use clone: "auto"; it attempts a native reflink and safely falls back to a sparse copy. Use clone: "reflink" only when failure is preferable to copying on a host filesystem without reflink support.

When the root-disk default is flat, plain msb pull IMAGE also prepares the reusable flat artifact. An explicit msb pull IMAGE --materialize layered|flat|all always wins.

runtime

FieldDefaultDescription
block_writeback{ "mode": "auto" }Buffered host writeback containment and live pressure sharing on Linux. Pool pressure never rejects sandbox creation; unconfigured auto is a no-op on other hosts.
placement_profiles{}Host-owned named CPU and NUMA placement profiles selectable by sandboxes

runtime.placement_profiles

Placement profiles let an operator define safe host topology policy once while callers select it by name. numa.mode is prefer_single, strict_single, or inherit; memory.mode is follow_cpu or inherit. Multi-node guest placement is not enabled in this release: prefer_single falls back to inherited host NUMA behavior when one node cannot fit, while strict_single fails clearly because it is an explicit guarantee.

follow_cpu requires managed CPU placement (auto, spread, or compact). Linux prefers the selected node for ordinary profiles and allows memory to spill elsewhere under pressure; strict_single uses a required binding instead. If CPUs span nodes, capacity is already insufficient, or the kernel rejects a best-effort affinity or memory-policy syscall, an ordinary profile starts with inherited memory placement. Windows keeps ordinary memory inherited because its preferred-node allocation cannot be undone if a later vCPU affinity attempt falls back; strict_single can still request required preferred-node allocation. Windows checks current boot-time availability, but does not expose equivalent per-node total capacity for a hard future-growth promise. macOS inherits ordinary CPU and memory scheduling for non-strict profiles because it has no equivalent hard-affinity API.

runtime.block_writeback

FieldModesDefaultDescription
modeall"auto"auto gives each eligible disk a measured 1536 MiB maximum and shares the aggregate pool when the host is busy, fixed requires an explicit maximum, and off disables both the VMM bound and host-global pressure coordination.
per_disk_mibfixedrequiredExplicit maximum for each eligible writable raw disk. The boot-time maximum is at least 128 MiB; the live fair share may fall below it under aggregate pressure. This field is rejected in auto and off modes.
pool_mibauto, fixednullOptional aggregate dirty-credit pressure-pool override. null derives the pool as the lower of 10% of physical RAM and a conservative estimate of Linux's dirty-background threshold, using the exact byte threshold when configured or the ratio applied to current MemAvailable. This field is rejected in off mode.

Use a fixed policy only when representative measurements justify a different per-disk window:

json
{
  "runtime": {
    "block_writeback": {
      "mode": "fixed",
      "per_disk_mib": 2048,
      "pool_mib": 12288
    }
  }
}

pool_mib is a live pressure budget, not eagerly allocated RAM. Every eligible writable disk in the same MSB_HOME receives a weighted max-min fair share: disks with a smaller configured maximum keep that smaller value, and the remaining pool is divided equally across the rest. Creating another sandbox never fails merely because this pool is full. Existing VMMs observe membership changes within 250 ms; if a disk already owns more dirty data than its new share, libkrun retires accounted ranges and pauses later writes until it converges below the target. A guest write already reserved before the target changed is allowed to complete safely. fixed and an explicitly pooled auto policy are unsupported on other hosts.

Hardware CRC32C, the guest kernel preemption model, x2APIC, APICv/AVIC capability, vCPU affinity mechanics, and the pure-Rust ext4 writer are implementation or capability details rather than user policy, so they intentionally have no global config keys. The optimization guide explains how those automatic layers interact with the configurable policy.

registries

FieldDefaultDescription
ca_certsnullPath to a PEM file with additional CA root certificates trusted for registry pulls
hosts{}Per-registry settings keyed by registry hostname

registries.hosts

A map of registry hostnames to settings. Each host entry can mark the registry as insecure (plain HTTP) and can include an auth entry. Each auth entry specifies a username and exactly one credential source.

json
{
  "registries": {
    "hosts": {
      "ghcr.io": {
        "auth": {
          "username": "octocat",
          "store": "keyring"
        }
      },
      "localhost:5050": {
        "insecure": true,
        "auth": {
          "username": "dev",
          "password_env": "LOCAL_REGISTRY_TOKEN"
        }
      }
    }
  }
}

Host entry fields

FieldRequiredDescription
insecureNoUse plain HTTP instead of HTTPS for this registry
authNoAuthentication entry for this registry

Auth entry fields

FieldRequiredDescription
usernameYesRegistry username
storeNoCredential store. Only "keyring" is supported (macOS Keychain, Windows Credential Manager, Linux Secret Service)
password_envNoEnvironment variable containing the password or token
secret_nameNoFilename under {home}/secrets/registries/ containing the password or token
<Note> Exactly one of `store`, `password_env`, or `secret_name` must be set per entry. Setting none or more than one is an error. </Note>

Auth resolution order

When pulling from a registry, microsandbox resolves credentials in this order:

  1. Explicit SDK auth via .registry(|r| r.auth(...)) on the sandbox builder
  2. OS keyring entries created by msb registry login
  3. Config file registries.hosts.<host>.auth entries in config.json
  4. Docker config ~/.docker/config.json credential helpers
  5. Anonymous (no authentication)

metrics

FieldDefaultDescription
capacity0Number of slots reserved in the live metrics shared-memory registry. 0 uses the built-in default. Stop all sandboxes for the same home before changing this value.

profiles

Named backend profiles keyed by profile name; active_profile selects the default. How profiles participate in backend selection, including the full resolution order, is documented in Backends.

FieldDefaultDescription
backendrequiredlocal or cloud
api_key_refnoneCredential reference; required for cloud profiles
urlhttps://api.microsandbox.devCloud endpoint override for development, self-hosted, or on-prem control planes

Supported credential references for api_key_ref:

PrefixDescription
env:<VAR_NAME>Read the API key from an environment variable
inline:<API_KEY>Store the API key directly in config.json; use only for development or CI