smol-machines/smolvm
🔗 https://github.com/smol-machines/smolvm ↗smolvm Ship and run software with isolation by default. This is a CLI tool that lets you: Manage and run custom Linux virtual machines locally with: sub-second cold start, cross-platform (macOS, Linux, Windows), elastic memory usage. 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/ . Windows: download the windows-x86_64 release (bundles krun.dll + libkrunfw.dll ), unzip it, and run smolvm.exe . Requires the Windows Hypervisor Platform (WHP) feature enabled. 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 Smolfile A Smolfile declares a machine in TOML, the equivalent of a Dockerfile or a cloud-init file, but for a whole VM: image, resources, network policy, mounts, ports, and setup commands in one checked-in file. image = " python:3.12-alpine " net = true cpus = 4 memory = 4096 ports = [ " 8000:8000 " , " 5173-5180:5173-5180 " ] volumes = [ " ./src:/app " ] init = [ " pip install -r /app/requirements.txt " ] [ network ] allow_hosts = [ " api.stripe.com " , " pypi.org " ] [ auth ] ssh_agent = true smolvm machine create --name myvm -s Smolfile # or --smolfile <PATH> smolvm machine start --name myvm Port mappings accept a single port ( "8080" ), an explicit mapping ( "8080:80" ), or equal-length one-to-one ranges ( "5173-5180:5173-5180" ). A machine can publish at most 64 concrete mappings. Unknown keys are rejected rather than ignored, so a typo fails at create time instead of silently doing nothing. Common keys: image , cpus , memory , net , ports , volumes , env , init (runs once as root, like a Dockerfile RUN ), workdir , user (who the workload runs as), gpu , cuda , docker_socket , storage , overlay , and the [network] , [dev] , [auth] , [health] , [restart] , [service] tables. Branch a running machine A branch is a live fork: an independent copy-on-write child that resumes with the source's running processes, memory, and disk. Start the source as branchable, then branch it: smolvm machine start --name source --branchable smolvm machine branch --from source --name child # checkpoints the source wherever it is To fan out many children from one checkpoint, the source's workload marks the point to take it by running smolvm-branch-ready once its setup is done, and names the program each child should run after it. The helper blocks in the source, which stays parked there; in each child it hands off to that program with the child's identity in its environment: # the workload: install, warm up, then "fork me here, and run this in each child" smolvm machine create --name source --image python:3.12-alpine --net -- sh -c ' pip install -q requests python3 serve.py & # keeps running in every child exec smolvm-branch-ready -- python3 episode.py ' smolvm machine start --name source --branchable smolvm machine branch --from source --count 8 --name-prefix worker --parallel 8 episode.py starts in each child with SMOLVM_BRANCH_NAME , SMOLVM_BRANCH_INDEX , SMOLVM_BRANCH_BATCH_ID , and SMOLVM_BRANCH_BATCH_SIZE set, plus any --env the branch command passed. A shell script that wants to continue inline instead runs eval "$(smolvm-branch-ready)" : the same command, whose output is those variables as export lines. machine exec sessions in a child see them in their environment too. When a child has its own warm-up after the branch (loading a checkpoint, binding a port), it can report the moment it is actually usable by running smolvm-worker-ready , and the branch command can wait for that instead of for the release alone: smolvm machine branch --from source --count 8 --name-prefix worker --wait-worker-ready With --wait-worker-ready (window: --worker-ready-timeout , default 5m) a child that never reports is torn down with its batch rather than handed back looking alive. machine branch-release takes the same flags for a held pool slot. Container rules apply, as in Docker: the container lives as long as its main process. exec smolvm-branch-ready with no program simply parks; the child keeps running with the helper as its init. A batch branch waits ( --ready-timeout , default 10m) for the source to reach its branchpoint; a single --name branch never waits. With --name-prefix or --hold , even a count of one is a batch and gets the same boundary, identity, and release. Add --branchable to a child when it must branch again. fork , --golden , and --forkable remain compatibility aliases. A branch takes a checkpoint of the source in memory; machine checkpoint saves that same state as a durable .smolcheckpoint artifact that can be restored later or elsewhere. Building checkpoint tooling in Rust? smolvm-checkpoint provides incremental storage, verified file restoration, and portable export without depending on the VM runtime. Snapshot a machine into a reusable image You don't need a Dockerfile to keep an environment. Set a machine up however you like (by hand, or from a Smolfile), then pack the stopped machine into a .smolmachine artifact and push it to any OCI registry: smolvm machine shell --name myvm # install and configure interactively smolvm machine stop --name myvm smolvm pack create --from-vm myvm -o myvm smolvm pack push --file myvm.smolmachine ghcr.io/you/myvm:v1 Anyone can then pull it and boot the exact same machine: smolvm pack pull ghcr.io/you/myvm:v1 Working Smolfiles: python · node · docker-in-vm · local-llm · headless-browser · doom 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, so 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, so there is no install step and no runtime downloads, and it 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 Use local container images for CI, air-gapped hosts, and fast iteration. Feed --image a docker save / podman save archive, pipe one on stdin, or point it at an unpacked rootfs directory. Image work is delegated to your container tooling; smolvm just boots the result. # build locally, run in the VM with no push/pull docker build -t myapp . docker save myapp | smolvm machine run --image - -- ./app # from an archive file (boots with no network) smolvm machine run --image ./myapp.tar -- ./app # from an already-unpacked rootfs directory smolvm machine run --image ./rootfs/ -- ./app Persistent machines for development. Create, stop, start. Installed packages survive restarts. smolvm machine create --net --name 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 Host directory mounts propagate host-side changes into guest inotify, so tools such as Vite, nodemon, and file-watch test runners reload without polling.
內容為收集當日抓取的 repo 描述原文,完整資訊請見 GitHub 原頁。