GitHub - smol-machines/smolvm: Tool to build & run portable, lightweight, self-contained virtual machines. · GitHub

Source: original

Discord Release License

smolvm

Ship and run software with isolation by default.

This is a CLI tool that lets you:

  1. Manage and run custom Linux virtual machines locally with: sub-second cold start, cross-platform (macOS, Linux), elastic memory usage.
  2. Pack a stateful virtual machine into a single file (.smolmachine) to rehydrate on any supported platform.

Install

install (macOS + Linux)

curl -sSL https://smolmachines.com/install.sh | bash

for coding agents — install + discover all commands

curl -sSL https://smolmachines.com/install.sh | bash && smolvm --help

Or download from GitHub Releases, and place it into ~/.local/share/.

Quick Start

run a command in an ephemeral VM (cleaned up after exit)

smolvm machine run --net --image alpine -- sh -c "echo 'Hello world from a microVM' && uname -a"

interactive shell

smolvm machine run --net -it --image alpine -- /bin/sh

inside the VM: apk add sl && sl && exit

Use This For

Sandbox untrusted code — run untrusted programs in a hardware-isolated VM. Host filesystem, network, and credentials are separated by a hypervisor boundary.

network is off by default — untrusted code can't phone home

smolvm machine run --image alpine -- nslookup example.com

fails — no network access

lock down egress — only allow specific hosts

smolvm machine run --net --image alpine --allow-host registry.npmjs.org -- wget -q -O /dev/null https://registry.npmjs.org

works — allowed host

smolvm machine run --net --image alpine --allow-host registry.npmjs.org -- wget -q -O /dev/null https://google.com

fails — not in allow list

Pack into portable executables — turn any workload into a self-contained binary. All dependencies are pre-baked — no install step, no runtime downloads, boots in <200ms.

smolvm pack create --image python:3.12-alpine -o ./python312 ./python312 run -- python3 --version

Python 3.12.x — isolated, no pyenv/venv/conda needed

Persistent machines for development — create, stop, start. Installed packages survive restarts.

smolvm machine create --net myvm smolvm machine start --name myvm smolvm machine exec --name myvm -- apk add sl smolvm machine exec --name myvm -it -- /bin/sh

inside: sl, ls, uname -a — type 'exit' to leave

smolvm machine stop --name myvm

Use git and SSH without exposing keys — forward your host SSH agent into the VM. Private keys never enter the guest — the hypervisor enforces this. Requires an SSH agent running on your host (ssh-add -l to check).

smolvm machine run --ssh-agent --net --image alpine -- sh -c "apk add -q openssh-client && ssh-add -l"

lists your host keys, but they can't be extracted from inside the VM

smolvm machine exec --name myvm -- git clone git@github.com:org/private-repo.git

Declare environments with a Smolfile — reproducible VM config in a simple TOML file.

image = "python:3.12-alpine" net = true

[network] allow_hosts = ["api.stripe.com", "db.example.com"]

[dev] init = ["pip install -r requirements.txt"] volumes = ["./src:/app"]

[auth] ssh_agent = true

smolvm machine create myvm -s Smolfile smolvm machine start --name myvm

More examples: python · node · doom

How It Works

Each workload gets real hardware isolation — its own kernel on Hypervisor.framework (macOS) or KVM (Linux). libkrun VMM with custom kernel: libkrunfw. Pack it into a .smolmachine and it runs anywhere the host architecture matches, with zero dependencies.

Images use the OCI format — the same open standard Docker uses. Any image on Docker Hub, ghcr.io, or other OCI registries can be pulled and booted as a microVM. No Docker daemon required.

Defaults: 4 vCPUs, 8 GiB RAM. Memory is elastic via virtio balloon — the host only commits what the guest actually uses and reclaims the rest automatically. vCPU threads sleep in the hypervisor when idle, so over-provisioning has near-zero cost. Override with --cpus and --mem.

Comparison

smolvm | Containers | Colima | QEMU | Firecracker | Kata

Isolation | VM per workload | Namespace (shared kernel) | Namespace (1 VM) | Separate VM | Separate VM | VM per container Boot time | <200ms | ~100ms | ~seconds | ~15-30s | <125ms | ~500ms Architecture | Library (libkrun) | Daemon | Daemon (in VM) | Process | Process | Runtime stack Per-workload VMs | Yes | No | No (shared) | Yes | Yes | Yes macOS native | Yes | Via Docker VM | Yes (krunkit) | Yes | No | No Embeddable SDK | Yes | No | No | No | No | No Portable artifacts | .smolmachine | Images (need daemon) | No | No | No | No

Platform Support

Host | Guest | Requirements

macOS Apple Silicon | arm64 Linux | macOS 11+ macOS Intel | x86_64 Linux | macOS 11+ (untested) Linux x86_64 | x86_64 Linux | KVM (/dev/kvm) Linux aarch64 | aarch64 Linux | KVM (/dev/kvm)

Known Limitations

GPU Acceleration

smolvm exposes the host GPU to guests via virtio-gpu / Venus (Vulkan-over-virtio). Guest workloads see a real Vulkan device; on Linux + Intel this renders as:

ANGLE (Intel, Vulkan 1.4 (Virtio-GPU Venus (Intel(R) UHD Graphics ...)), venus)

Host requirements

macOS — virglrenderer and MoltenVK are bundled in the smolvm distribution. No extra installs needed.

Linux — virglrenderer and a host Vulkan driver must be installed from the system package manager:

Distro | Packages

Alpine | apk add virglrenderer mesa-vulkan-intel (or mesa-vulkan-ati for AMD) Debian/Ubuntu | apt install virglrenderer0 mesa-vulkan-drivers

virglrenderer depends on libEGL and libdrm from the host GPU driver stack — these are hardware-specific and cannot be bundled. Any GPU-capable Linux host will already have them installed via its GPU driver.

Usage

CLI

smolvm machine run --gpu --image alpine -- vulkaninfo --summary

Smolfile

gpu = true

gpu_vram = 2048 # MiB, default 4096

The guest Vulkan loader must be pointed at the virtio ICD:

export VK_ICD_FILENAMES=/usr/share/vulkan/icd.d/virtio_icd.x86_64.json

Headless browser example

See examples/headless-browser/ for a working Chromium setup using ANGLE + Venus for hardware-accelerated WebGL inside a headless VM.

Development

See docs/DEVELOPMENT.md.

Apache-2.0 · made by @binsquare · twitter · github