Skip to main content

Overview

VMConfig is a Pydantic model that defines the configuration for creating a microVM. It specifies CPU, memory, kernel, rootfs, and other runtime settings.

Model Definition

class VMConfig(BaseModel)
All VMConfig instances are immutable (frozen) after creation.

Fields

vm_id
str
default:"auto-generated"
Unique identifier for the VM. Must be lowercase alphanumeric with hyphens, matching the pattern ^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$ or ^[a-z0-9]$.If omitted or explicitly set to None, SmolVM auto-generates an ID in the format vm-<8-char-hex>.
vcpu_count
int
default:"2"
Number of virtual CPUs. Valid range: 1-32.
mem_size_mib
int
default:"512"
Memory size in MiB (mebibytes). Valid range: 128-16384.
kernel_path
Path
required
Path to the kernel image file. The path must exist and point to a valid file.
rootfs_path
Path
required
Path to the root filesystem image. The path must exist and point to a valid file.
boot_args
str
default:"console=ttyS0 reboot=k panic=1 pci=off"
Kernel boot arguments. For SSH-capable VMs built with ImageBuilder, include init=/init.
backend
str | None
default:"None"
Runtime backend override. Valid options:
  • "firecracker": Use Firecracker VMM
  • "qemu": Use QEMU
  • None or "auto": Auto-detect based on host capabilities
disk_mode
Literal['isolated', 'shared']
default:"isolated"
Disk lifecycle mode:
  • "isolated": Clone rootfs per VM for sandbox isolation. Each VM gets its own copy.
  • "shared": Boot directly from rootfs_path. Multiple VMs can share the same disk image.
retain_disk_on_delete
bool
default:"False"
Whether to keep the isolated VM disk after deletion. When True, a later create operation with the same VM ID can reuse prior disk state.Only applies when disk_mode="isolated".
env_vars
dict[str, str]
default:"{}"
Environment variables to inject into the guest after boot via SSH. Keys must be valid shell identifiers (matching ^[a-zA-Z_][a-zA-Z0-9_]*$).Variables are persisted in /etc/profile.d/smolvm_env.sh and affect new SSH sessions/login shells.Requires an SSH-capable image (boot args must contain init=/init).

Validation Rules

Path Validation

Both kernel_path and rootfs_path are validated to ensure:
  1. The path exists on the filesystem
  2. The path points to a file (not a directory)
Validation occurs during model instantiation.

Environment Variable Validation

All keys in env_vars must be valid shell identifiers:
  • Start with a letter or underscore
  • Contain only letters, numbers, and underscores
  • Pattern: ^[a-zA-Z_][a-zA-Z0-9_]*$
Invalid keys raise a ValidationError during model instantiation.

VM ID Validation

The vm_id must:
  • Be lowercase
  • Start and end with alphanumeric characters
  • Contain only lowercase letters, numbers, and hyphens
  • Be 1-64 characters long

Usage Examples

Basic Configuration

from smolvm import VMConfig
from pathlib import Path

config = VMConfig(
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
)

print(config.vm_id)  # Auto-generated, e.g., "vm-a1b2c3d4"
print(config.vcpu_count)  # 2 (default)
print(config.mem_size_mib)  # 512 (default)

Custom VM ID and Resources

from smolvm import VMConfig
from pathlib import Path

config = VMConfig(
    vm_id="my-custom-vm",
    vcpu_count=4,
    mem_size_mib=2048,
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
)

SSH-Capable VM with Environment Variables

from smolvm import VMConfig, SSH_BOOT_ARGS
from pathlib import Path

config = VMConfig(
    vm_id="api-server",
    vcpu_count=2,
    mem_size_mib=1024,
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/alpine-ssh.ext4"),
    boot_args=SSH_BOOT_ARGS,  # Includes init=/init for SSH support
    env_vars={
        "API_KEY": "secret-key",
        "DATABASE_URL": "postgresql://localhost/mydb",
        "LOG_LEVEL": "debug",
    },
)

Shared Disk Mode

from smolvm import VMConfig
from pathlib import Path

# Multiple VMs can boot from the same rootfs
config = VMConfig(
    vm_id="shared-vm-1",
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/shared/rootfs.ext4"),
    disk_mode="shared",
)

Persistent Isolated Disk

from smolvm import VMConfig
from pathlib import Path

# Keep VM disk after deletion for state persistence
config = VMConfig(
    vm_id="stateful-vm",
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
    disk_mode="isolated",
    retain_disk_on_delete=True,
)

# Later, create a new VM with the same ID to reuse the disk
config2 = VMConfig(
    vm_id="stateful-vm",  # Same ID
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
    disk_mode="isolated",
)

QEMU Backend

from smolvm import VMConfig
from pathlib import Path

config = VMConfig(
    vm_id="qemu-vm",
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
    backend="qemu",
    boot_args="console=ttyAMA0 reboot=k panic=1 init=/init",
)

Immutability

VMConfig instances are frozen and cannot be modified after creation:
config = VMConfig(
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
)

# This raises an error
config.vcpu_count = 4  # ValidationError: "VMConfig" is frozen

# Instead, create a new instance
from pydantic import BaseModel

new_config = config.model_copy(update={"vcpu_count": 4})

Integration with SmolVM

Pass VMConfig to the SmolVM constructor:
from smolvm import SmolVM, VMConfig
from pathlib import Path

config = VMConfig(
    vm_id="my-vm",
    vcpu_count=2,
    mem_size_mib=512,
    kernel_path=Path("/path/to/vmlinux"),
    rootfs_path=Path("/path/to/rootfs.ext4"),
    boot_args="console=ttyS0 reboot=k panic=1 init=/init",
)

with SmolVM(config) as vm:
    result = vm.run("echo 'Hello from configured VM'")
    print(result.stdout)

Building Images for VMConfig

Use ImageBuilder to create kernel and rootfs images:
from smolvm import ImageBuilder, VMConfig, SmolVM
from pathlib import Path

# Build an SSH-capable Alpine Linux image
builder = ImageBuilder()
public_key = Path("~/.ssh/id_rsa.pub").expanduser().read_text()

kernel, rootfs = builder.build_alpine_ssh_key(
    public_key=public_key,
    name="my-alpine",
    rootfs_size_mb=512,
)

# Use the built images in VMConfig
config = VMConfig(
    vm_id="alpine-vm",
    kernel_path=kernel,
    rootfs_path=rootfs,
    boot_args="console=ttyS0 reboot=k panic=1 init=/init",
)

with SmolVM(config) as vm:
    result = vm.run("cat /etc/os-release")
    print(result.stdout)

Field Summary

FieldTypeDefaultRange/Validation
vm_idstrAuto-generated^[a-z0-9][a-z0-9-]{0,62}[a-z0-9]$
vcpu_countint21-32
mem_size_mibint512128-16384
kernel_pathPathRequiredMust exist as file
rootfs_pathPathRequiredMust exist as file
boot_argsstr"console=ttyS0 reboot=k panic=1 pci=off"Any string
backendstr | NoneNone"firecracker", "qemu", None
disk_modeLiteral"isolated""isolated", "shared"
retain_disk_on_deleteboolFalseTrue, False
env_varsdict[str, str]{}Keys must be valid shell identifiers
Last modified on March 3, 2026