mvmctl docs
mvmctl documentation
Everything you need to install, configure, and manage microVMs with mvmctl. Covers every command with explanations, callouts, and real-world examples.
Before you begin
mvmctl runs on Linux only — Firecracker requires KVM, which is not available on macOS or Windows. Make sure your system meets these requirements before installing.
- Linux host (x86_64 or aarch64) with KVM support — check with
ls /dev/kvm - Access to
/dev/kvmand membership in thekvmgroup - Go 1.26.3+ to build from source (optional — binary install does not require Go)
- Root access once for host setup (
mvm inithandles this for you) nftablesfor NAT and firewall rules (default backend)
System packages
mvmctl depends on a few system tools for networking, image handling, and cloud-init:
Terminal
sudo apt-get install -y iproute2 iptables nftables qemu-utils e2fsprogs util-linux procps kmod openssh-client tar sudo passwd fakerootTerminal
sudo pacman -S --needed iproute2 iptables nftables qemu-img e2fsprogs util-linux procps-ng kmod openssh tar sudo shadow fakerootmvm --help to verify installation. Install mvm
Two ways to install. The prebuilt binary is the fastest — no Go toolchain needed.
No Go toolchain required. Best for production machines.
Terminal
# Get the latest binary from the Releases page
# https://github.com/AlanD20/mvmctl/releases
mkdir -p ~/.local/bin
curl -L -o ~/.local/bin/mvm https://github.com/AlanD20/mvmctl/releases/latest/download/mvm
chmod +x ~/.local/bin/mvm
mvm --helpAvailable as mvmctl-bin for Arch Linux users.
Terminal
yay -S mvmctl-bin
mvm --helpFor local development or contributing. Requires Go 1.26.3+.
Terminal
git clone https://github.com/AlanD20/mvmctl
cd mvmctl
./scripts/build.sh release --output ~/.local/bin/mvm
mvm --helpmvm --help to verify. If "command not found", ensure ~/.local/bin is in your PATH. Initialize host
Before creating any VMs, your host needs one-time setup: KVM module loading, IP forwarding, the mvm group, sudoers permissions, and bridge networking. This is what mvm init handles for you.
Interactive setup (recommended)
Run mvm init — it walks you through host config (sudo/group/sudoers), Firecracker binary download, cache initialization, service binary extraction, and default asset setup. Escalates to root automatically when needed.
Terminal
mvm initnewgrp mvm to avoid logging out. One-time host setup
Run mvm init to perform the one-time machine setup. It is idempotent — safe to re-run.
Terminal
mvm initmvm init escalates to root when needed. It creates the mvm system group, writes sudoers drop-in files, loads KVM kernel modules, enables IP forwarding, and sets up bridge/TAP networking. Normal mvm commands do not need sudo after this runs. What host init actually does
- Loads
kvm,kvm_intel/kvm_amdkernel modules (networking modulestunandbridgeare loaded as needed) - Enables
net.ipv4.ip_forwardfor NAT networking - Creates the
mvmsystem group and adds your user to it - Writes a sudoers drop-in to
/etc/sudoers.d/mvmso mvmctl can run privileged commands (ip, iptables, sysctl, modprobe) without password prompts - Sets up the
mvm-netbridge and firewall chains for NAT
mvm init flags
Control the interactive wizard behavior with these flags:
Terminal
# Non-interactive mode — use defaults, skip all prompts
mvm init --non-interactive
# Skip host init step (useful if host is already configured)
mvm init --skip-host
# Skip default network creation
mvm init --skip-network
# Combine flags for fully automated setup
mvm init --non-interactive --skip-host--skip-host and --skip-network to skip both host setup and default network creation. Useful when re-running mvm init to only pull new assets. Other host commands
Terminal
mvm host status # Show current host configuration state vs expected — useful for verifying setup
mvm host status --json # Show current host configuration state as JSON
mvm host info # Show host hardware, limits, and VM capacity projection
mvm host info --refresh # Re-detect hardware and limits before displaying
mvm host info --json # Output as JSON
mvm host clean # Remove networking config only (bridges, TAPs, iptables rules)
mvm host reset # Full rollback — networking, sysctl, sudoers, and the mvm groupmvm host reset is destructive. It removes the mvm group, meaning anyone in it loses mvm access. Only use if you are permanently uninstalling mvmctl. Create your first VM
This walkthrough takes you from zero to a running microVM: generate an SSH key, download a kernel and OS image, boot the VM, connect, and clean up.
Step by step
Create a complete microVM from scratch: generate an SSH key, download a kernel and OS image, boot the VM, connect, and clean up.
Terminal
# 1. Generate an SSH key for VM access
mvm key create my-key --default
# 2. Download Firecracker-optimized kernel (~30s)
mvm kernel pull --type firecracker
# 3. Download an Ubuntu 24.04 image
mvm image pull ubuntu --version 24.04
# 4. Create and start the VM
mvm vm create myvm --image ubuntu:24.04
# 5. Wait for cloud-init to finish (~30-60s)
mvm logs myvm --follow
# 6. SSH into the VM
mvm ssh myvm
# 7. List running VMs
mvm vm ls
# 8. Remove the VM when done
mvm vm rm myvm -fmvm logs myvm --follow. mvm key create NAME --default or pass --ssh-key explicitly when creating a VM. ~/.cache/mvmctl/. mvm vm create
Creates and immediately starts a Firecracker microVM. Under the hood mvmctl: (1) copies the root filesystem image to a per-VM directory, (2) generates a Firecracker JSON boot config, (3) picks an available IP from the network lease pool, (4) starts a temporary HTTP server for cloud-init, (5) launches Firecracker (+ jailer). There is no separate "start" command — the VM boots right away.
All flags
Terminal
VM_NAME (positional) VM name (required). Used to identify the VM in all commands.
--image IMAGE Image name, type:version (e.g. ubuntu:24.04), short ID, or path to .ext4 file. Auto-detected from defaults if omitted.
--kernel KERNEL Kernel short ID or path to vmlinux. Auto-detected from defaults if omitted.
--vcpu N Number of vCPUs (default: from user config).
--mem, --memory N Memory in MiB or GiB (e.g. 512M, 1G) (default: from user config).
--disk-size, -s SIZE Rootfs disk size (e.g. 1G, 512M or 1024M). Default: from config.
--ssh-key KEY SSH public key name (from key cache) or file path.
--user USER Default SSH user for cloud-init. Default: from config.
--ip ADDRESS Static guest IP, e.g. 172.27.0.42. Default: auto-assigned.
--network, --net NAME Named network to attach to. Default: 'net'.
--mac ADDRESS Custom MAC address. Auto-generated if omitted.
--cloud-init-mode MODE One of: off (default), inject, iso, net.
--cloudinit-config PATH Path to custom cloud-init configuration file.
--nocloud-net-port PORT Port for nocloud-net HTTP server (0=auto-assign).
--no-pci Disable PCI transport (default: enabled). Required for hotplug support.
--nested-virt Enable nested virtualization (requires PCI, adds kvm-intel/amd.nested=1 boot arg)
--cpu-template PATH Path to CPU template JSON file (merged with nested-virt config if both set)
--console Enable serial console relay (default: disabled).
--lsm-flags FLAGS Linux Security Module flags for kernel cmdline.
--enable-logging Enable Firecracker logging.
--enable-metrics Enable Firecracker metrics.
--boot-args ARGS Custom kernel boot arguments (e.g. 'console=ttyS0 reboot=k panic=1').
--writeback Use writeback cache mode for drives.
--vsock-port PORT Vsock port for the guest agent (default: 1024).
--allow-remote-exec Allow inter-VM remote execution (VM→Host→VM relay). Disabled by default.
--skip-cleanup Skip cleanup on failure (for debugging).
--skip-deblob Skip debloat operations on rootfs (removes OS caches, package manager caches).
--count, -c N Number of VMs to create (default: 1).
--atomic If any VM fails, remove all successfully-created VMs (all-or-nothing).
--volume, -v NAME Attach a volume to the VM (can be specified multiple times).
--force, -f Skip confirmation prompts.Examples
Minimal — get a default VM running fast
Terminal
# Assuming kernel + image fetched, default key set:
mvm vm create myvm --image ubuntu:24.04Defaults: 1 vCPU, 512 MiB RAM, auto-assigned IP on network net (172.27.0.0/24).
Custom resources
Terminal
mvm vm create \
build-vm \
--image ubuntu:24.04 \
--vcpus 4 \
--mem 8192 \
--disk-size 50GUseful for CI runners or compiling in isolated environments.
Specific network and static IP
Terminal
# First create a network
mvm network create isolated --subnet 10.0.0.0/24
# Then attach the VM with a fixed IP
mvm vm create myvm --image ubuntu:24.04 --network isolated --ip 10.0.0.50The IP must fall within the network subnet. Default network net uses 172.27.0.0/24.
Non-root user and custom SSH key
Terminal
mvm key create workstation-key --default
mvm vm create \
dev-vm \
--image ubuntu:24.04 \
--ssh-key workstation-key \
--user ubuntuThe --user flag sets the cloud-init default user. This user gets password-less sudo inside the VM.
Alpine — lightweight and fast
Terminal
mvm image pull alpine --version 3.21
mvm vm create tiny-vm --image alpine:3.21 --vcpus 1 --mem 256Alpine boots in seconds. Great for testing or ephemeral workloads.
Custom cloud-init user-data
Terminal
# Write a custom user-data file
cat > my-user-data.yaml << 'EOF'
#cloud-config
package_update: true
packages:
- htop
- build-essential
EOF
# Pass it to the VM
mvm vm create myvm --image ubuntu:24.04 --cloudinit-config my-user-data.yamlCustom user-data merges with mvmctl's default cloud-init. You can add packages, write files, run commands, etc.
Batch creation with atomic rollback
Terminal
# Create 5 VMs atomically — if any fails, all are removed
mvm vm create cluster --image ubuntu:24.04 --count 5 --atomic
# With a volume attached to a single VM
mvm volume create shared-data 10G
mvm vm create worker --image ubuntu:24.04 --volume shared-dataThe --count flag auto-generates names by appending -1, -2, etc. The --atomic flag ensures no partial creation — all created VMs are rolled back if any single VM fails. --count and --volume are mutually exclusive (a volume can only be attached to one VM). Implicit IP and MAC assignment is used (no --ip or --mac with --count > 1).
mvm vm create starts the VM immediately. net) uses 172.27.0.0/24. Leases are reused when VMs are removed. --disk-size flag resizes via qemu-img resize. It only grows the image — shrinking requires manual intervention. --ssh-key and have no default key, the VM will boot but you cannot SSH in. Use mvm console for serial access instead. VM Lifecycle
Once your VM is created, these commands let you interact with, inspect, snapshot, and tear it down.
mvm ssh
SSH into a running VM by name. Resolves the VM name to its IP address from the lease database and connects with the cached SSH key.
Terminal
mvm ssh myvmSSH as the default user (root by default unless --user was specified).
Terminal
mvm ssh myvm --user adminSSH as a specific user.
Terminal
mvm ssh myvm --cmd "uname -a"Execute a command non-interactively.
Terminal
mvm ssh myvm --key mykeyUse a specific SSH key.
Terminal
mvm ssh myvm --timeout 10Set connection timeout in seconds.
ssh -i commands. But you do need a key set up beforehand. mvm console
Attaches a PTY-based serial console to a VM using a vsock relay. No network stack required. Works even if the VM has no IP or cloud-init failed.
Terminal
mvm console myvmAttach to the VM serial console interactively.
Terminal
mvm console myvm --stateCheck if the console relay is running (does not attach).
Terminal
mvm console myvm --killKill a stuck console relay.
Ctrl+X then D to detach from the console session. This does not shut down the VM. mvm console --kill then re-attach. --state to check if the relay is running without attaching. Handy for scripting. vhost_vsock kernel module. Check with lsmod | grep vsock. mvm exec
Execute a command inside a VM via the vsock guest agent. No SSH or network stack required — works over the vsock channel directly.
Terminal
mvm exec myvm -- uname -aRun a command as root and see output.
Terminal
mvm exec myvm --user ubuntu -- whoamiRun a command as a specific user.
Terminal
mvm exec myvm --timeout 30 -- long-running-commandOverride the default vsock probe timeout.
Terminal
mvm exec myvm --no-sync -- echo "fast"Skip final sync for faster execution.
Terminal
mvm exec myvm --port 1025 -- my-commandSpecify a custom vsock port.
mvm ssh --cmd, mvm exec does not need SSH keys or a network connection. It uses the vsock agent inside the VM. --user to run as a specific user (default: root). --timeout to set the vsock agent connect/probe timeout in seconds. --no-sync to skip the final sync() (faster but risks data loss on VM stop). mvm logs
View or stream VM logs. Two types: boot (serial console — kernel boot messages, cloud-init, login prompts) and OS (Firecracker process stderr/stdout).
Terminal
mvm logs myvm --followWatch the VM boot in real-time. Best for checking if cloud-init finished.
Terminal
mvm logs myvm --osCheck Firecracker stderr — useful if the VM failed to start.
Terminal
mvm logs myvmView the full boot log (static, not following).
--follow / -f streams logs in real-time (like tail -f). Press Ctrl+C to stop. --os to show Firecracker process logs instead of serial console output. --lines / -n to limit output to the last N lines. ~/.cache/mvmctl/vms/<vm-sha>/ as firecracker.console.log and firecracker.log. mvm vm snapshot / load
Create and restore VM snapshots — save memory and disk state to disk, then restore later. Useful for preserving a long-running VM state before rebooting the host.
Terminal
mvm snapshot create myvmSnapshot a running VM. Saves memory and disk state.
Terminal
mvm snapshot lsList all snapshots.
Terminal
mvm snapshot inspect <snapshot-id>Show detailed snapshot information.
Terminal
mvm snapshot restore <snapshot-id> <vm-name>Restore the VM from a saved snapshot.
Terminal
mvm snapshot rm <snapshot-id>Remove a snapshot.
~/.cache/mvmctl/snapshots/<id>/. mvm cp
Copy files between the host and microVMs using a binary frame protocol over vsock. The vsock agent inside the VM handles file transfer operations.
Terminal
mvm cp local-file.txt myvm:/home/Copy a file from host to VM.
Terminal
mvm cp myvm:/var/log/syslog ./Copy a file from VM to host.
Terminal
mvm cp myvm1:/data/file.txt myvm2:/data/Copy a file between two VMs.
Terminal
mvm cp *.txt myvm:/dst/Shell glob expands to multiple files (host → VM only).
vm_name:/remote/path for VM paths, plain /local/path for local paths. mvm vm ps
List only running VMs (active Firecracker processes). Shows name, status, IP, resources, and image/kernel IDs.
Terminal
mvm vm psShow only VMs that are currently running or starting.
mvm vm ls / inspect
Shows detailed VM information: SHA256 hash ID, IP address, network, kernel path, image path, resources, creation time, current state, and vsock agent config (guest CID, UDS path, port, agent version, upgrade state).
Terminal
mvm vm inspect myvmShow all details for a VM.
Terminal
mvm vm lsList all VMs with brief info (name, IP, status).
Terminal
mvm vm ls --jsonList all VMs with JSON output.
mvm vm rm / prune
Stops the Firecracker process, removes firewall rules, kills the nocloud-net server, and deletes the VM state directory.
Terminal
mvm vm rm myvmRemove a VM with confirmation.
Terminal
mvm vm rm myvm -fRemove without asking (script-friendly).
Terminal
mvm cache prune vmRemove all stopped VMs at once.
--force / -f, the command asks for confirmation. Use --force / -f in scripts. mvm cache prune vm removes all stopped VMs at once. Asks for confirmation by default. mvm vm ls until removed with rm or prune. Resource Management
mvmctl manages five resource types: OS images (root filesystems), kernels (vmlinux binaries), Firecracker/jailer binaries, SSH keys, and persistent data disks (volumes).
mvm image
What images are
Images are root filesystem images (ext4 format) that provide the OS for your microVM. mvmctl can fetch pre-built images from the registry or import local files.
Available images
These image types are defined in mvmctl and can be fetched with mvm image pull <type>:<version> (e.g. mvm image pull ubuntu:24.04) or the longer mvm image pull <type> --version <version> — or use mvm image ls --remote to see all available versions:
ubuntu— Ubuntu LTS (tar-rootfs). Versions: 26.04, 24.04, 22.04, 20.04ubuntu-minimal— Ubuntu Minimal (tar-rootfs). Versions: 26.04, 24.04, 22.04, 20.04debian— Debian (qcow2). Versions: 13, 12, 11alpine— Alpine Linux (VHD). Versions: 3.x releasesarchlinux— Arch Linux (qcow2, rolling release — no version needed)firecracker— Firecracker CI Ubuntu (squashfs, from Firecracker S3 bucket)
Fetching images
Terminal
# Fetch an image by type and version
mvm image pull ubuntu --version 24.04
# Shorthand: type:version syntax
mvm image pull ubuntu:24.04
# Alpine Linux
mvm image pull alpine --version 3.21
# Or use shorthand:
mvm image pull alpine:3.21
# Arch Linux (rolling release — no version needed)
mvm image pull archlinux
# Force re-download (overwrites cached copy)
mvm image pull ubuntu:24.04 -f
# Skip cached version listing and fetch live
mvm image pull ubuntu:24.04 --no-cache
# Disable specific detectors (type,label,size,filesystem,all)
mvm image pull ubuntu:24.04 --disable-detector type,label
# Set as default after download
mvm image pull ubuntu:24.04 --default
# List available images (local + remote versions)
mvm image ls
mvm image ls --remote # Show upstream versions
mvm image ls --remote --no-cache # Bypass cache, fetch live from upstreammvm img <command> can be used instead of mvm image <command>. Images are typically 200-800 MB compressed. Cached in ~/.cache/mvmctl/images/. Each VM gets its own copy. Importing custom images
Import a rootfs from a file or create a reusable base image from a running VM:
Terminal
# From a VM selector — create a reusable base image from a VM's rootfs
mvm image import base-img my-vm
# From a VM selector, with a version tag
mvm image import base-img:v1.0 my-vm --version v2.0
# From a file (qcow2, raw, tar-rootfs)
mvm image import my-custom-image /path/to/my-custom-image.raw --format raw
# Overwrite existing image
mvm image import myimg /path/to/image.raw --force
# Set as default after import
mvm image import myimg /path/to/image.raw --default
# Skip filesystem optimization (shrink/compression)
mvm image import myimg /path/to/image.raw --skip-optimization
# Disable specific detectors
mvm image import myimg /path/to/image.raw --disable-detector type
mvm image ls # Verify it shows up
mvm image default my-custom-imagemvm image import NAME [SOURCE | VM_SELECTOR]. When the second argument is a VM selector (name or ID), mvmctl copies that VM's rootfs to create a reusable image. Supports raw images (.raw/.img), qcow2, and tar-rootfs archives (.tar/.tar.gz/.tar.xz/.tgz) from files. Managing images
Terminal
mvm image ls # List all cached images
mvm image inspect <id> # Show detailed image info
mvm image default <id> # Set default for new VMs
mvm image rm <id> # Remove a cached image (full or short SHA)
mvm image warm <id> # Pre-decompress to ready pool for fast VM creationmvm kernel
What kernels are
Firecracker requires an uncompressed ELF binary (vmlinux) — not the compressed vmlinuz used by traditional bootloaders. mvmctl supports two kernel types.
Firecracker-optimized kernel (recommended)
A pre-built kernel from the Firecracker CI pipeline. Minimally configured for fast boot — no PCI, no ACPI. Downloads in ~30 seconds.
Terminal
mvm kernel pull --type firecracker
# Downloads the latest Firecracker-optimized kernelOfficial upstream kernel (custom build)
Downloads the official Linux kernel source (default: 6.19.9) and compiles it with a Firecracker-compatible config. Takes 10-30 minutes.
Terminal
# Build latest upstream kernel
mvm kernel pull --type official
# Using type:version shorthand
mvm kernel pull official:6.19.9
# Build a specific version
mvm kernel pull --type official --version 6.6
# Apply a custom kernel config fragment
mvm kernel pull --type official --config /path/to/my-fragment.config
# Enable kernel features (kvm, nftables)
mvm kernel pull official:6.19.9 --features kvm,nftables
# Specify parallel build jobs
mvm kernel pull --type official --jobs 8
# Set as default after fetch
mvm kernel pull --type official --default
# Force clean rebuild (bypass cache)
mvm kernel pull --type official --clean-build
# Keep the build directory for debugging
mvm kernel pull --type official --keep-build-dirbuild-essential, flex, bison, libelf-dev, libssl-dev, libncurses-dev, bc, git, curl, pkg-config, dwarves (for pahole). Expect 10-30 min build times. Use --config PATH to apply a custom kernel config fragment, --jobs N for parallel build jobs, and --default to set as default after fetch. Managing kernels
Terminal
mvm kernel ls # List cached kernels
mvm kernel ls --remote # List remote versions available for download
mvm kernel inspect <id> # Show detailed kernel info
mvm kernel default <id> # Set as default for VM creation
mvm kernel import <name> <path> # Import a custom vmlinux kernel file
mvm kernel rm <id> # Remove a cached kernelKernel feature reference
The --features flag applies pre-defined kernel config fragments on top of the base Firecracker config. Multiple features can be combined (e.g. --features kvm,nftables,tuntap). Use --features all or --features * to enable every feature in the spec. Enabled features are persisted and shown in mvm kernel inspect. Defined in kernels.yaml.
| Feature | Description | Key config enforced |
|---|---|---|
| kvm | Nested KVM virtualization | CONFIG_KVM, CONFIG_KVM_INTEL / CONFIG_KVM_AMD |
| nftables | nftables NAT firewall backend | CONFIG_NFT_NAT, CONFIG_NF_TABLES_INET, CONFIG_NFT_MASQ |
| tuntap | TUN/TAP device support (VM networking) | CONFIG_TUN |
| btrfs | Btrfs filesystem support | CONFIG_BTRFS_FS, CONFIG_BTRFS_FS_POSIX_ACL |
| containers | Container runtime core (containerd/runc) | CONFIG_NAMESPACES, CONFIG_CGROUPS, CONFIG_SECCOMP, CONFIG_OVERLAY_FS, CONFIG_IKCONFIG, CONFIG_IKCONFIG_PROC |
| iptables | iptables kube-proxy backend | CONFIG_NETFILTER, CONFIG_NETFILTER_XTABLES, CONFIG_IP_NF_NAT, CONFIG_NF_CONNTRACK, CONFIG_IP_SET, CONFIG_NETFILTER_XT_SET, CONFIG_NETFILTER_XT_MARK, CONFIG_NETFILTER_XT_TARGET_CT |
| cni-bridge | CNI bridge / overlay networking | CONFIG_BRIDGE, CONFIG_VETH, CONFIG_MACVLAN, CONFIG_IPVLAN, CONFIG_VXLAN, CONFIG_GENEVE, CONFIG_FIB_RULES |
| ebpf | eBPF / BTF (Cilium, bpftool) | CONFIG_BPF, CONFIG_BPF_JIT, CONFIG_DEBUG_INFO_BTF, CONFIG_BPF_EVENTS, CONFIG_PERF_EVENTS, CONFIG_NET_CLS_BPF, CONFIG_NET_CLS_ACT, CONFIG_NET_SCH_INGRESS |
| storage | Filesystems for persistent volumes | CONFIG_EXT4_FS, CONFIG_XFS_FS, CONFIG_BTRFS_FS, CONFIG_BLK_DEV_NVME |
| fqdn-proxy | L7 / FQDN policy proxy (TPROXY, xt_socket) | CONFIG_NETFILTER_XT_TARGET_TPROXY, CONFIG_NETFILTER_XT_TARGET_CT, CONFIG_NETFILTER_XT_MATCH_SOCKET |
| bandwidth | Bandwidth manager (FQ packet scheduler) | CONFIG_NET_SCH_FQ |
| iscsi-target | iSCSI target mode (Longhorn block storage) | CONFIG_TARGET_CORE, CONFIG_ISCSI_TARGET, CONFIG_ISCSI_TCP, CONFIG_BLK_DEV_SD |
| ebpf-cni | eBPF-based CNI networking (Cilium, Hubble) | CONFIG_BPF, CONFIG_DEBUG_INFO_BTF, CONFIG_VXLAN, CONFIG_GENEVE, CONFIG_IP_SET, CONFIG_NETFILTER_XT_TARGET_TPROXY, CONFIG_NETFILTER_XT_MATCH_SOCKET |
| iscsi-target | iSCSI target mode (Longhorn block storage) | CONFIG_TARGET_CORE, CONFIG_ISCSI_TARGET, CONFIG_ISCSI_TCP, CONFIG_BLK_DEV_SD |
| ebpf-cni | eBPF-based CNI networking (Cilium, Hubble) | CONFIG_BPF, CONFIG_DEBUG_INFO_BTF, CONFIG_VXLAN, CONFIG_GENEVE, CONFIG_IP_SET, CONFIG_NETFILTER_XT_TARGET_TPROXY, CONFIG_NETFILTER_XT_MATCH_SOCKET |
mvm bin
What binaries are
Firecracker and jailer binaries downloaded from the Firecracker GitHub releases page. You need at least one version downloaded to create VMs.
Managing binaries
Terminal
# Download Firecracker v1.15.0 (includes jailer)
mvm bin pull firecracker --version 1.15.0
# Build Firecracker from source at a git ref
mvm bin pull firecracker --git-ref v1.15.0
# Force re-download even if version already exists
mvm bin pull firecracker --version 1.15.0 --force
# List downloaded versions
mvm bin ls
# JSON output for scripting
mvm bin ls --json
# List remote versions available for download
mvm bin ls --remote
# Set as active version by ID prefix
mvm bin default abc123
# Remove by version
mvm bin rm --version 1.15.0
mvm bin rm --version 1.15.0 -f # Force remove even if referenced by VMs
# Remove by ID
mvm bin rm abc123mvm bin pull downloads both firecracker and jailer together. They must match versions — mixing v1.14 firecracker with v1.15 jailer causes runtime errors. mvm key
What keys are for
SSH public keys cached by mvmctl for injection into VMs via cloud-init. Without at least one key, you cannot SSH into your VMs (console access still works).
Creating and managing keys
Terminal
# Generate a new ED25519 keypair and set as default (recommended)
mvm key create mykey --default
# Import an existing public key
mvm key import mykey ~/.ssh/id_ed25519.pub
mvm key import mykey ~/.ssh/id_ed25519.pub --force # Overwrite if key exists
# List all cached keys
mvm key ls
# Show key details
mvm key inspect mykey
# Set default keys for VM creation
mvm key default mykey
# Clear all default keys
mvm key default --clear
# Export a key to a directory
mvm key export mykey ~/.ssh/exported
# Remove a key from cache
mvm key rm mykeymvm key create generates both a public and private key. The private key stays on your machine — mvmctl only stores the public key for cloud-init injection. How keys work with VMs
When you create a VM with --ssh-key mykey (or use the default key), mvmctl injects the public key into cloud-init user-data. After cloud-init finishes (~30-60s), you can SSH in with mvm ssh myvm.
mvm volume
What volumes are
Volumes are persistent data disks that can be attached to VMs and survive VM removal. They are stored as raw or qcow2 disk images in the cache directory and managed through the mvmctl database.
Creating volumes
Create a new persistent volume with a name and size:
Terminal
# Create a 10 GB raw volume
mvm volume create data-disk 10G
# Create a qcow2 volume (supports grow and shrink)
mvm volume create data-disk 10G --format qcow2
# Create a read-only volume (writable by default)
mvm volume create data-disk 10G --read-only
# Create a 512 MB volume for testing
mvm volume create test-disk 512Mmvm vol <command> can be used instead of mvm volume <command>. Raw format (default) uses fallocate for fast allocation. Qcow2 format supports both grow and shrink via qemu-img. The volume name must be unique. Listing volumes
Terminal
# List all volumes with ID, name, format, size, status, and VM
mvm volume ls
# JSON output for scripting
mvm volume ls --jsonInspecting volumes
Show detailed information about a volume including disk metadata:
Terminal
mvm volume inspect data-disk
mvm volume inspect abc123 # ID prefix also worksRemoving volumes
Terminal
# Remove by name
mvm volume rm data-disk
# Remove multiple volumes
mvm volume rm data-disk test-disk
# Force remove even if attached to a VM
mvm volume rm data-disk -f--force / -f is used. Detach first with mvm volume detach. Resizing volumes
Grow (or shrink qcow2) an existing volume to a new size:
Terminal
# Resize to 20 GB (grow only for raw format)
mvm volume resize data-disk 20G
# Raw volumes: grow only (fallocate)
# Qcow2 volumes: grow and shrink (qemu-img)Attaching volumes to VMs
Volumes can be attached and detached from running VMs using the VM command group:
Terminal
# Attach a volume when creating a VM
mvm vm create myvm --image ubuntu:24.04 --volume data-disk
# Attach to a running VM (via Firecracker API)
mvm volume attach myvm data-disk
# Detach from a running VM
mvm volume detach myvm data-diskNetwork Management
mvmctl uses Linux bridge/TAP networking with NAT (via nftables or iptables). Each named network is a separate bridge with its own subnet.
How networking works
mvmctl uses Linux bridge/TAP networking with NAT (via nftables or iptables). Each named network is a Linux bridge with its own subnet. VMs get TAP interfaces and IPs from a lease pool. Traffic is NATed to the host network.
The default network
The default network is called net and uses 172.27.0.0/24 (gateway: 172.27.0.1). It is created automatically the first time you run mvm host init — no manual network setup needed for basic use.
net. The bridge device is named mvm-net (mvm-net), following the convention mvm-<network-name>. Network commands
Terminal
# Create a named network with a custom subnet
# You will be prompted to select interface(s) for NAT
mvm network create mynet --subnet 10.0.1.0/24
# Create non-interactively (skips NAT gateway prompts)
mvm network create mynet --subnet 10.0.1.0/24 --non-interactive
# Create with explicit NAT gateway interfaces
mvm network create mynet --subnet 10.0.1.0/24 --nat-gateways eth0
# Create without NAT (no internet access for VMs)
mvm network create mynet --subnet 10.0.1.0/24 --no-nat
# Create with explicit gateway IP
mvm network create mynet --subnet 10.0.1.0/24 --ipv4-gateway 10.0.1.1
# Create and set as default network
mvm network create mynet --subnet 10.0.1.0/24 --default
# List all networks
mvm network ls
# Show network details
mvm network inspect mynet
# Set a network as default
mvm network default mynet
# Sync firewall rules between database and host
mvm network sync
# Remove a network (only if no VMs attached)
mvm network rm mynetmvm net <command> can be used instead of mvm network <command>. You cannot remove a network that has VMs attached. Stop and remove the VMs first. Using networks with VMs
Terminal
# Create a VM on a custom network
mvm network create isolated --subnet 10.0.0.0/24
mvm vm create myvm --image ubuntu:24.04 --network isolated
# Assign a specific IP
mvm vm create myvm --image ubuntu:24.04 --network isolated --ip 10.0.0.50Custom networks get the subnet you specify. The bridge device is named mvm-<network-name>. Each VM gets a unique MAC address (auto-generated with the 02:FC prefix).
Configuration
Configuration priority
Settings resolve in this order (lower overrides higher):
- Built-in defaults from
constants.go(compiled into the binary, lowest priority) - SQLite database (
~/.cache/mvmctl/mvmdb.db) — canonical store for user overrides MVM_*environment variables (e.g.MVM_LOG_LEVEL,MVM_CACHE_DIR)- CLI flags (highest priority)
Config and cache location
All configuration is stored in the SQLite database at ~/.cache/mvmctl/mvmdb.db (override with MVM_CACHE_DIR). The config directory at ~/.config/mvmctl/ holds SSH keys (override with MVM_CONFIG_DIR).
Config commands
Terminal
# List all overridable settings and their current values
mvm config list
# Get a specific value
mvm config get defaults.vm vcpu_count
# Set a value (persists to database)
mvm config set defaults.vm vcpu_count 4
# Reset a single value to default
mvm config reset defaults.vm vcpu_count
# Reset all overrides globally
mvm config reset --allEnvironment variables
Terminal
MVM_CACHE_DIR Override cache directory ~/.cache/mvmctl
MVM_CONFIG_DIR Override config directory ~/.config/mvmctl
MVM_LOG_LEVEL Log level: DEBUG, INFO, WARN, ERROR WARN (CLI flags recommended)
MVM_WARM_POOL Warm image pool backend (disk or tmpfs) tmpfs (default)
MVM_TEMP_DIR Override temp directory for microVMs /tmp/mvmctl
MVM_ESCALATED Set by sudo wrapper to indicate 1
privilege escalation
MVM_ASSET_MIRROR Local directory for asset mirroring
MVM_SUDO_RESTART Set internally when re-running (not set)
<code>mvm init</code> with sudo--verbose (sets INFO) and --debug (sets DEBUG) CLI flags are the recommended way to control log level — they take precedence over MVM_LOG_LEVEL. The env var falls back to WARN if neither flag is set and the variable is unset. Cache management
Terminal
# Initialize cache directories
mvm cache init
# Prune specific resource type
mvm cache prune vm
mvm cache prune network
mvm cache prune image
mvm cache prune kernel
mvm cache prune binary
mvm cache prune misc
# Dry-run prune all (see what would be removed)
mvm cache prune --all --dry-run
# Prune all resources including protected items
mvm cache prune --all
# Prune all without confirmation
mvm cache prune --all --force
# Completely clean all cache (nuclear option)
mvm cache clean
mvm cache clean --dry-run--dry-run first. Cache pruning is one-way. mvm cache clean removes ALL cached assets AND host networking, but does not touch running VMs unless you use --all. Shell Completion
Shell completion
Generate tab-completion scripts for your shell. Uses Cobra's built-in generators — completions adapt automatically as commands change. Supports bash, zsh, fish, and PowerShell.
Terminal
# bash — add to ~/.bashrc
source <(mvm completion bash)
# zsh — add to ~/.zshrc (inline)
source <(mvm completion zsh)
# zsh — or place in fpath for compinit auto-load
mvm completion zsh > "${fpath[1]}/_mvm"
# fish
mvm completion fish > ~/.config/fish/completions/mvm.fishmvm completion --help for the full installation guide per shell. Self-Update
mvm self-update
Check for and apply binary updates from GitHub Releases. Downloads the latest release matching your architecture and verifies the SHA256 checksum before swapping.
Terminal
mvm self-update # Check + apply if newer
mvm self-update check # Check only, print available version
mvm self-update apply # Force apply (even if same version)Dependencies
mvmctl depends on several system binaries. Most are common Linux utilities; this reference covers what each is for and which package provides it.
Core runtime dependencies
These binaries are required for basic mvmctl operations:
| Binary | Purpose | Debian/Ubuntu | RHEL/Fedora | Arch |
|---|---|---|---|---|
firecracker + jailer | MicroVM VMM + security isolation | mvm bin pull | mvm bin pull | mvm bin pull |
ip | Bridge/TAP management | iproute2 | iproute2 | iproute2 |
iptables | NAT and firewall rules | iptables | iptables | iptables |
iptables-save | Persisting iptables rules | iptables | iptables | iptables |
nft / nftables | NAT and firewall rules (default backend) | nftables | nftables | nftables |
sysctl | IP forwarding | procps | procps-ng | procps-ng |
modprobe | KVM module loading | kmod | kmod | kmod |
lsmod | KVM module status | kmod | kmod | kmod |
groupadd | mvm group creation | passwd | shadow | shadow |
usermod | User group membership | passwd | shadow | shadow |
visudo | Sudoers validation | sudo | sudo | sudo |
sudo | Privileged commands | sudo | sudo | sudo |
groupdel | Removing the mvm group on reset | passwd | shadow | shadow |
dumpe2fs | Filesystem inspection | e2fsprogs | e2fsprogs | e2fsprogs |
Image & cloud-init dependencies
| Binary | Purpose | Debian/Ubuntu | RHEL/Fedora | Arch |
|---|---|---|---|---|
qemu-img | Image conversion/resize | qemu-utils | qemu-img | qemu-img |
sfdisk | Partition table manipulation | util-linux | util-linux | util-linux |
blkid | Root partition/UUID detection | util-linux | util-linux | util-linux |
mount/umount | Image mounting | util-linux | util-linux | util-linux |
truncate | Sparse file creation | coreutils | coreutils | coreutils |
mkfs.ext4 | Rootfs formatting | e2fsprogs | e2fsprogs | e2fsprogs |
fakeroot | Preserve tarball ownership during extraction | fakeroot | fakeroot | fakeroot |
unsquashfs | SquashFS extraction | squashfs-tools | squashfs-tools | squashfs-tools |
tar | Tarball extraction | tar | tar | tar |
cloud-localds | Cloud-init seed ISO | cloud-image-utils | cloud-utils | cloud-utils |
ssh-keygen | SSH key generation | openssh-client | openssh | openssh |
ssh | VM connection | openssh-client | openssh | openssh |
libguestfs (optional — for cloud-init direct injection)
Required only if you enable the GuestFS backend via mvm config set settings guestfs_enabled true. The loop-mount provisioner is the default and does not require libguestfs.
Terminal
# Debian/Ubuntu
sudo apt-get install libguestfs0 libguestfs-tools supermin
# RHEL/CentOS/Fedora
sudo dnf install libguestfs libguestfs-tools supermin
# Arch
sudo pacman -S libguestfs superminBuilding kernels from source
Building official kernels from source requires additional build dependencies (make, gcc, flex, bison, libelf, openssl, ncurses, bc, pahole, git, curl, pkg-config). See the full custom-kernel guide for details.
Provisioning backend
mvmctl handles provisioning internally through a configurable backend. See the project documentation for backend details.
Command dependencies
Each mvmctl command may depend on system tools that are verified during mvm init. See DEPENDENCIES.md for details.
Host system requirements
- Kernel modules:
kvm,kvm_intelorkvm_amd,tun,bridge,vhost_vsock,nft_chain_nat - Hardware virtualization: VT-x (Intel) or AMD-V must be enabled in BIOS/UEFI
- Permissions: The user must be in the
mvmgroup (created bymvm host init)
Cloud-Init
Cloud-init configures your VM on first boot: users, SSH keys, networking, startup scripts. mvmctl handles this automatically.
What is cloud-init?
Cloud-init configures your VM on first boot: sets up users, injects SSH keys, configures networking, runs startup scripts. mvmctl handles this automatically.
How mvmctl handles cloud-init
Defaults to off if not specified. Set via --cloud-init-mode on mvm vm create. The available modes are:
Cloud-init modes
inject— injects cloud-init files directly into the rootfs via the active provisioner backend (loop-mount by default, or guestfs if enabled). Fastest and most reliable.net— starts a temporary HTTP server (nocloud-net). The VM fetches config during boot viads=nocloud;seedfrom=http://GATEWAY_IP:PORT/. No libguestfs needed.iso— attaches a CD-ROM ISO with cloud-init files. Compatible with all images. Slower (requirescloud-localds).off(default) — disables cloud-init entirely. VM boots with no user setup.
How nocloud-net (net mode) works
- A temporary HTTP server starts on an available port (8000-9000 range)
- Firewall rules allow only the specific VM to reach its server
- The VM boots with the nocloud-net kernel command line datasource
- Cloud-init fetches
meta-data,user-data, andnetwork-configvia HTTP - The HTTP server auto-cleans up when the VM is removed
Security model
- Each VM gets its own HTTP server on a unique port
- Source-based firewall rules — only the VM's IP can reach its server
- Servers bind to the bridge gateway IP, not
0.0.0.0 - Rules are tagged with
# nocloudnet:<vm_name>:<port>
Troubleshooting
Common issues, what causes them, and how to fix them:
Permission denied: /dev/kvm
Terminal
# First check if /dev/kvm exists:
ls -l /dev/kvm
# Case 1 — does not exist (KVM modules not loaded):
sudo modprobe kvm
sudo modprobe kvm_intel # or kvm_amd on AMD
# Case 2 — exists but not writable (group membership):
sudo usermod -aG kvm $USER
# Then log out and back inIf /dev/kvm does not exist after modprobe, install KVM modules (e.g. linux-modules-extra-* on Ubuntu). Group membership takes effect on next login.
Bridge mvm-net not found
Terminal
# The bridge is created automatically. Ensure host init ran:
mvm initRe-running mvm init is safe (idempotent). The default bridge is named mvm-net.
Image not found
Terminal
mvm image pull ubuntu --version 24.04
mvm image ls # Verify it appearsImage IDs are case-sensitive. Use mvm image ls to see available images.
Kernel not found
Terminal
mvm kernel pull --type firecracker
mvm kernel ls # Verify it is cached
mvm kernel ls --remote # List available remote versionsDefault fetch downloads a Firecracker-optimized kernel (~30s). Official builds take 10-30 min.
Firecracker binary not found
Terminal
mvm bin pull firecracker --version 1.15.0
mvm bin default <id>Always run mvm bin default <id> after fetching. The default version (e.g. 1.15.0) matches the installed Firecracker release — you can also pull other versions with mvm bin pull firecracker --version <version>.
VM won't boot / SSH times out
Terminal
# Watch boot progress:
mvm logs myvm --follow
# If nothing at all, check Firecracker process log:
mvm logs myvm --osWait at least 60 seconds before assuming the VM is stuck. If the boot log shows nothing, the kernel may be incompatible or the image corrupt.
NoCloud-net server failed to start
Terminal
# Port range (8000-9000) may be exhausted
sudo ss -tlnp | grep -E ':(8[0-9]{3}|9[0-9]{3})'
# Kill orphaned servers
pkill -f "mvm run nocloudnet serve"Each VM uses one port in 8000-9000. If many VMs were not cleaned up, orphaned servers may still be running.
Mixed firewall backends (Docker conflict)
Terminal
# Symptom: VM has IP, ping works, but TCP times out
# Detection:
mvm config get settings firewall_backend
sudo nft list ruleset | grep -c 'MVM-'
# Fix 1: sync firewall rules from database
mvm network sync
# Fix 2: reboot host (clears all firewall state cleanly)
sudo reboot
# Fix 3: Configure Docker to use the same backend as mvmctl
# Then re-run: mvm host initDocker and mvmctl may use different firewall backends (nftables vs iptables-legacy). Rules go to different places. mvm network sync reloads rules from the database.
Network creation fails with permission denied
Terminal
# Check mvm group membership
groups | grep mvm
# If not in group:
sudo usermod -aG mvm $USER
# Then log out and back inThe mvm group also requires a new login session. Use newgrp mvm to avoid logging out.
Console relay not working
Terminal
# Check relay status
mvm console myvm --state
# Kill and re-attach
mvm console myvm --kill
mvm console myvmThe console relay uses vsock. Ensure vhost_vsock kernel module is loaded: lsmod | grep vsock.
Cache corruption or stale state
Terminal
# Preview what would be removed
mvm cache prune --all --dry-run
# Remove stale entries from a specific type
mvm cache prune vm
# Full reset (removes ALL VMs — careful!)
mvm cache prune --allCache corruption usually shows as metadata pointing to deleted files, or phantom VMs. mvm cache prune reconciles metadata with actual files.
Volume attach fails — volume is already attached
Terminal
# Check volume status
mvm volume inspect my-data
# Detach from current VM first
mvm volume detach <vm-name> my-data
# Force remove (use with caution)
mvm volume rm my-data -fA volume can only be attached to one VM at a time. Detach it first or create a new volume. Use --force / -f on volume rm to skip the attached check.
Debug mode
Enable verbose logging to see what mvmctl is doing under the hood:
Terminal
# Run a single command with verbose (INFO) output:
mvm --verbose vm create myvm --image ubuntu:24.04
# Run a single command with debug (DEBUG) output:
mvm --debug vm create myvm --image ubuntu:24.04
# Or use the MVM_LOG_LEVEL env var (takes precedence over defaults,
# but CLI flags --verbose/--debug take precedence over the env var):
MVM_LOG_LEVEL=DEBUG mvm vm create myvm --image ubuntu:24.04--verbose flag sets INFO level; --debug sets DEBUG level. CLI flags take precedence over MVM_LOG_LEVEL. Falls back to WARN if neither flag nor env var is set. Getting help
Still stuck? Open an issue on GitHub with:
- The exact command you ran
- Full error output (run with
MVM_LOG_LEVEL=DEBUG) - Your OS and
mvm --version