> ## Documentation Index
> Fetch the complete documentation index at: https://docs.microsandbox.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Runtime setup

> Prepare a local runtime before creating your first sandbox.

Local sandboxes need `msb` and `libkrunfw`. Call the setup helper once at application startup: it reuses an existing runtime or installs one when missing. Sandbox creation does not download it automatically. Cloud sandboxes do not need a local runtime.

## Set up the runtime

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { ensureRuntime } from "microsandbox";

  const runtime = await ensureRuntime();
  console.log(runtime.msbPath, runtime.libkrunfwPath);
  ```

  ```rust Rust theme={null}
  use microsandbox::{config::GlobalConfig, setup::{InstallOptions, ensure_runtime}};

  let runtime = ensure_runtime(&GlobalConfig::default(), InstallOptions::default()).await?;
  ```

  ```python Python theme={null}
  from microsandbox import ensure_runtime

  runtime = await ensure_runtime()
  print(runtime.msb_path, runtime.libkrunfw_path)
  ```

  ```go Go theme={null}
  import (
      "fmt"
      m "github.com/superradcompany/microsandbox/sdk/go"
  )

  runtime, err := m.EnsureRuntime(ctx, m.RuntimeConfig{}, m.InstallOptions{})
  if err != nil {
      return err
  }
  fmt.Println(runtime.MSBPath, runtime.LibkrunfwPath)
  ```

  ```ruby Ruby theme={null}
  require "microsandbox"

  Microsandbox.install unless Microsandbox.installed?
  ```
</CodeGroup>

The default installation directory is `~/.microsandbox` (`%USERPROFILE%\.microsandbox` on Windows). Keep `msb` and `libkrunfw` from the same runtime bundle.

<h3 id="resolve-check-install-and-ensure">
  Choose a setup operation
</h3>

Use ensure for normal startup. The calls below are alternatives; choose the one your application needs.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import * as msb from "microsandbox";

  await msb.ensureRuntime();  // Reuse or install if missing.
  msb.resolveRuntime();       // Require an existing runtime; never install.
  msb.isRuntimeInstalled();   // Check availability; returns a boolean.
  await msb.installRuntime(); // Install from the selected source.
  ```

  ```rust Rust theme={null}
  use microsandbox::{config::GlobalConfig, setup};

  let config = GlobalConfig::default();

  // Reuse or install if missing.
  setup::ensure_runtime(&config, Default::default()).await?;
  // Require an existing runtime; never install.
  setup::resolve_runtime(&config)?;
  // Check availability; returns a boolean.
  setup::is_runtime_installed(&config);
  // Install from the selected source.
  setup::install_runtime(&config, Default::default()).await?;
  ```

  ```python Python theme={null}
  import microsandbox as msb

  await msb.ensure_runtime()  # Reuse or install if missing.
  msb.resolve_runtime()       # Require an existing runtime; never install.
  msb.is_runtime_installed()  # Check availability; returns a boolean.
  await msb.install_runtime() # Install from the selected source.
  ```

  ```go Go theme={null}
  import m "github.com/superradcompany/microsandbox/sdk/go"

  config := m.RuntimeConfig{}
  options := m.InstallOptions{}

  // Reuse or install if missing. Returns (ResolvedRuntime, error).
  m.EnsureRuntime(ctx, config, options)
  // Require an existing runtime. Returns (ResolvedRuntime, error).
  m.ResolveRuntime(config)
  // Check availability; returns bool.
  m.IsRuntimeInstalled(config)
  // Install from the selected source. Returns (ResolvedRuntime, error).
  m.InstallRuntime(ctx, config, options)
  ```
</CodeGroup>

Ensure does not repair incomplete installations or ignore invalid explicit paths.

<h2 id="choose-a-runtime">
  How runtime selection works
</h2>

The SDK checks these locations in order:

1. **Explicit paths:** environment variables, process-level setters, then configured paths.
2. **Runtime home:** configured `home`, then `MSB_HOME`, then `~/.microsandbox`.
3. **SDK package:** bundled binaries, when available.

A local backend captures its effective home, relative directory overrides, configured runtime paths, and registry CA certificate path when it is constructed. Later changes to the working directory or `MSB_HOME` do not move that backend's files. Construct a new backend to select another home. Relative host paths in global `config.json` and managed configuration resolve against the contributing file’s directory. Programmatic paths and environment defaults use the caller’s working directory. Process-level SDK runtime setters capture relative paths when registered; environment runtime overrides are captured during backend construction, below managed policy. Existing saved sandbox records retain their legacy relative-path interpretation without rewriting.

A complete home installation wins over bundled Python and Node runtimes, even if its version differs from the SDK. Updating an SDK does not replace that installation. Go also reuses a complete home installation. [Managed runtime paths](/enterprise/deploy-and-verify#apply-configuration-updates) override user choices.

To use a custom installation, set both `MSB_PATH` and `MSB_LIBKRUNFW_PATH` before constructing a backend. See [path overrides](/sdk/setup#override-runtime-paths) for SDK setters and precedence details.

## Advanced setup

### Bring your own runtime

Install a matching pair with the [CLI installer](/getting-started/quickstart), or provision it yourself and select its paths above.

* **Node:** the platform package includes the runtime and native addon. `--omit=optional` also removes the required addon.
* **Rust:** embedding is opt-in. To also disable the default Cargo-time runtime download:

```bash theme={null}
cargo add microsandbox --no-default-features --features local,net
```

You can still call `setup::ensure_runtime()` explicitly with these features.

### Use a custom kernel

If your workload needs additional Linux kernel features, build a custom `libkrunfw`, the library that bundles the guest kernel. This applies to local sandboxes; it does not change the managed cloud kernel.

<Note>
  Start from the `vendor/libkrunfw` revision pinned by your microsandbox release in our [libkrunfw fork](https://github.com/superradcompany/libkrunfw). It includes the kernel patches microsandbox relies on; an upstream build may not be compatible.
</Note>

1. Enable the required kernel options or apply your patches, then follow the [build instructions](https://github.com/superradcompany/libkrunfw#building) for your platform and architecture.
2. Select the compatible `msb` executable and your rebuilt library before starting your application.

For example, on Linux, replace these paths with your executable and custom library:

```bash theme={null}
export MSB_PATH="/opt/microsandbox/bin/msb"
export MSB_LIBKRUNFW_PATH="/opt/custom-kernel/libkrunfw.so.5"
```

You can also use the [SDK path setters](#override-runtime-paths). In Rust, `set_sdk_libkrunfw_path()` is process-wide, not a `SandboxBuilder` method; call it before constructing the backend.

Boot a fresh guest to use the new kernel. Running guests and full snapshots retain their existing kernel.

### Offline installation

Use a directory or archive source to install a pre-downloaded release bundle. To require an installation that already exists, call the resolve helper instead of ensure. See [installation examples and options](/sdk/setup#customize-installation) and [offline deployment](/enterprise/prepare-environment#prepare-offline-devices).

### Embedded runtime

If your SDK build includes an embedded runtime archive, you can install from it without downloading. Select the `embedded_archive` source in the [installation options](#customize-installation).

Ensure reuses an existing runtime before extracting the archive. Resolve only finds an existing installation; it does not extract one.

## Troubleshooting

| Problem | What to do |
| - | - |
| Incomplete installation | Restore a matching executable and library. Setup does not repair a partial pair or fall back to bundled binaries. |
| Invalid explicit path | Correct the override. Invalid paths do not fall through to another installation. |
| Unexpected runtime version | Check explicit paths and the runtime home; both take precedence over bundled binaries. |
| Feature unsupported by an older runtime | Upgrade the selected runtime. Updating the SDK alone may leave it unchanged. |
| Embedded archive unavailable | Use a native SDK built with embedding, or choose a directory, archive, or download source. |

For existing installations, see the [v0.7 migration guide](/migrations/v0.7) before upgrading a shared database. Helper details are available below.

## API reference

<AccordionGroup>
  <Accordion title="Customize installation" id="customize-installation">
    Python, TypeScript, and Go accept a `RuntimeConfig` and `InstallOptions`. Their per-call home and binary-path overrides are layered on persisted global configuration. Rust accepts `GlobalConfig` and `InstallOptions` directly. Environment binary-path overrides retain the highest priority.

    Use the directory source to provision a runtime from a flat release-bundle directory containing `msb` and `libkrunfw` side by side, without downloading:

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { installRuntime } from "microsandbox";

      const runtime = await installRuntime(
        { home: "/opt/microsandbox" },
        { source: "directory", sourcePath: "/opt/runtime-bundle" },
      );
      ```

      ```rust Rust theme={null}
      use microsandbox::{
          config::GlobalConfig,
          setup::{InstallOptions, InstallSource, install_runtime},
      };

      let config = GlobalConfig { home: Some("/opt/microsandbox".into()), ..Default::default() };
      let runtime = install_runtime(&config, InstallOptions {
          source: InstallSource::Directory("/opt/runtime-bundle".into()),
          ..Default::default()
      }).await?;
      ```

      ```python Python theme={null}
      from microsandbox import InstallOptions, RuntimeConfig, install_runtime

      runtime = await install_runtime(
          RuntimeConfig(home="/opt/microsandbox"),
          InstallOptions(source="directory", source_path="/opt/runtime-bundle"),
      )
      ```

      ```go Go theme={null}
      runtime, err := m.InstallRuntime(ctx,
          m.RuntimeConfig{Home: "/opt/microsandbox"},
          m.InstallOptions{Source: m.InstallSourceDirectory, SourcePath: "/opt/runtime-bundle"},
      )
      if err != nil {
          return err
      }
      ```
    </CodeGroup>

    | Option | Behavior |
    | - | - |
    | Home and binary paths | Select the runtime home or explicit pair for this call. |
    | Source | `release_download` (default), `directory`, `archive`, or `embedded_archive`; directory and archive require a source path. |
    | Version | Select the release to download; defaults to the SDK's pinned release. |
    | Force | Replace a complete installation; never repair a partial pair. |
    | Verify | Verify the installed pair; defaults to true. Go uses `*bool` so its zero value preserves this default. |
    | Expected archive SHA-256 | Validate downloaded, local, or embedded archive bytes before publishing files. |

    An embedded source requires a native SDK built with an embedded runtime archive. If unavailable, explicit installation errors. Ensure still reuses an existing pair before acquisition, even when an embedded source is requested. To require a pre-provisioned runtime, call resolve directly. Each call uses its own configuration; Go no longer caches a process-wide successful setup result.
  </Accordion>

  <Accordion title="Override runtime paths" id="override-runtime-paths">
    The TypeScript, Rust, Python, and Ruby SDKs can override process-wide runtime paths directly. Call setters before creating a local sandbox. Automatic package discovery is a fallback and does not occupy the explicit setter slot. A public libkrunfw setter overrides the library for the selected executable, whether that executable comes from configured paths, home, or a package.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { setRuntimeLibkrunfwPath } from "microsandbox";

      setRuntimeLibkrunfwPath("/opt/microsandbox/lib/libkrunfw.dylib");
      ```

      ```rust Rust theme={null}
      use microsandbox::config::{set_sdk_libkrunfw_path, set_sdk_msb_path};

      set_sdk_msb_path("/opt/microsandbox/bin/msb");
      set_sdk_libkrunfw_path("/opt/microsandbox/lib/libkrunfw.dylib");
      ```

      ```python Python theme={null}
      from microsandbox import set_libkrunfw_path

      set_libkrunfw_path("/opt/microsandbox/lib/libkrunfw.dylib")
      ```

      ```ruby Ruby theme={null}
      require "microsandbox"

      Microsandbox.set_runtime_libkrunfw_path("/opt/microsandbox/lib/libkrunfw.dylib")
      ```
    </CodeGroup>

    Set runtime paths before constructing a backend. Each backend captures these settings; create a new backend to pick up changes. Environment variables work across the SDKs and take precedence over SDK-provided or user-configured paths. [Managed runtime paths](/enterprise/deploy-and-verify#apply-configuration-updates) take precedence over all three:

    | Variable | Purpose |
    | - | - |
    | `MSB_PATH` | Override the `msb` executable used by local SDK operations. |
    | `MSB_LIBKRUNFW_PATH` | Override the `libkrunfw` shared library loaded by the process. |
    | `MSB_AGENTD_PATH` | Override the Agentd guest executable read by `msb` before VM startup. |

    Set these process-wide overrides before creating any local sandbox. Prefer setting `MSB_PATH` and `MSB_LIBKRUNFW_PATH` together to select a matching pair. `MSB_PATH` alone may resolve a library adjacent to that executable; `MSB_LIBKRUNFW_PATH` alone is incomplete and fails closed. An incomplete explicit pair is not repaired by falling back to another installation. `MSB_AGENTD_PATH` takes precedence over global `paths.agentd`; the selected file is read eagerly and must name a compatible Linux ELF executable. These variables do not belong to an individual sandbox configuration.
  </Accordion>

  <Accordion title="Read a runtime version" id="read-a-runtime-version">
    TypeScript and Rust can read the Cargo package version embedded in an `msb` executable without running it. This is an optional inspection of the specified file; firmware and a complete runtime installation are not required.

    <CodeGroup>
      ```typescript TypeScript theme={null}
      import { resolveRuntimeVersion } from "microsandbox";

      const version = await resolveRuntimeVersion("/path/to/msb");
      ```

      ```rust Rust theme={null}
      use microsandbox::setup::resolve_runtime_version;

      let version = resolve_runtime_version("/path/to/msb")?;
      ```
    </CodeGroup>

    Rust returns `Option<setup::Version>` and TypeScript returns `string | null`. Older executables without the version section produce `None` or `null`. Invalid executable metadata, malformed version sections and file access failures are errors. The reader supports ELF, PE and thin or universal Mach-O files, limits metadata reads to 4 MiB and version contents to 256 bytes, and never falls back to executing `msb --version`. Universal Mach-O slices must agree on the version, including section absence. The version identifies the build; it does not authenticate the executable or guarantee feature compatibility.

    Sandbox startup separately resolves a tested launch contract for the selected runtime. When embedded version metadata is absent, startup may run a bounded `msb --version` probe and cache the result for that native executable's identity within the SDK process. Replacing the executable invalidates that cache. This startup behavior does not change the read-only version inspection methods above.
  </Accordion>

  <Accordion title="Inspect Go versions" id="inspect-go-versions">
    Go setup helpers may load the SDK's embedded FFI library on first use; resolve does not install host runtime binaries.

    Go also exposes the SDK's pinned release version and the version reported by the loaded FFI library:

    ```go theme={null}
    sdkVersion := m.SDKVersion()

    runtimeVersion, err := m.RuntimeVersion()
    if err != nil {
        return err
    }
    ```

    `SDKVersion() string` does not load the FFI library. `RuntimeVersion() (string, error)` loads it automatically on first use and returns an error if loading fails.
  </Accordion>

  <Accordion title="Compatibility: setup APIs before v0.7" id="earlier-setup-apis">
    These APIs were replaced in v0.7.0. Use this mapping when upgrading from v0.6; new applications should use the current helpers above.

    | SDK | Replace | With |
    | - | - | - |
    | TypeScript | `install` | `installRuntime` |
    | TypeScript | `isInstalled` | `isRuntimeInstalled` |
    | Python | `install` | `install_runtime` |
    | Python | `is_installed` | `is_runtime_installed` |
    | Go | `EnsureInstalled` | `EnsureRuntime` |
    | Go | `IsInstalled` | `IsRuntimeInstalled` |

    * **TypeScript:** replace the `setup` / `Setup` builder with runtime helpers accepting `RuntimeConfig` and `InstallOptions`.
    * **Go:** replace `SetupOption` with `RuntimeConfig` and `InstallOptions`. Replace `WithSkipDownload` with `ResolveRuntime` when installation must be avoided.

    Install and ensure now return the selected runtime paths. Rust's four helper names and Ruby's setup API are unchanged. See [setup operations](#resolve-check-install-and-ensure).
  </Accordion>
</AccordionGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.