Skip to main content

microheart: run Firecracker microVMs with one command

microheart

Boot a Firecracker microVM with one command or three lines of Python. No Python dependencies. Linux with KVM only.

Unofficial. Not affiliated with or endorsed by Amazon Web Services. "Firecracker" is an AWS project and name.

Status: alpha. The code has not been tested on a real host yet. Test it before you rely on it. See SECURITY.md for the known limits.

What it does

Firecracker is a very small virtual machine monitor (3.6 MB). It starts a Linux guest in about a second, but you must do many manual steps first: get the binary, get a kernel, build a disk, make a network device, set NAT, write the API calls. microheart does these steps for you.

Step By hand With microheart
Firecracker binary download, unpack fetch (or bundled in the wheel)
Guest kernel find on S3, download fetch (or bundled in the wheel)
Root disk Docker image, export, mkfs.ext4 build-rootfs
Network ip tuntap, iptables, forwarding up
Boot 5 curl calls to the API socket up (one --config-file)
Login key, route, DNS inside the guest key, route and DNS are in the disk
Clean up remove TAP and NAT rule down

Requirements

To run a VM

  • Linux, x86_64 (or aarch64), with /dev/kvm readable and writable by root
  • Root access (sudo): TAP devices and iptables need it
  • ip, iptables, sysctl, ssh (normally present)
  • Python 3.9 or newer
  • A virtualization-capable host. A cloud VM works if nested virtualization is on (tested idea: DigitalOcean droplet)

To build the root disk (once, on any machine)

  • Docker, mkfs.ext4, e2fsck, ssh-keygen

Docker is not needed to run the VM. Build the disk once and copy the .ext4 file.

Install

The tool needs root (TAP devices, iptables). Install it system-wide with pipx, so that microheart works from any folder, also with sudo:

sudo apt-get install -y pipx
sudo PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx install microheart
microheart --version

Update later with sudo PIPX_HOME=/opt/pipx PIPX_BIN_DIR=/usr/local/bin pipx upgrade microheart.

You can also use pip install microheart, but inside a virtual environment the command is only at <venv>/bin/microheart and is not on your PATH. Use pipx to avoid that.

Quick start

microheart fetch                 # Firecracker + kernel (skipped when bundled in the wheel)
microheart build-rootfs          # build alpine.ext4 + an SSH key (needs Docker)
microheart up                    # boot the VM and wait for SSH
microheart ssh uname -a          # run one command, or open a shell without arguments
microheart down                  # stop the VM, remove tap0 and the NAT rule

Run these as root (sudo -i first, or put sudo in front). Files go to ~/.cache/microheart/ (change with MICROHEART_HOME). With sudo, ~ is root's home.

Command reference

Command What it does
microheart fetch Get the Firecracker binary and the newest CI kernel into the cache.
microheart build-rootfs [--size 512M] [--output FILE] Build the ext4 disk from the bundled Dockerfile. Make an ed25519 key if none exists.
microheart up Make tap0, set NAT, write the config file, start Firecracker, wait for SSH.
microheart ssh [command...] SSH to the guest at 172.16.0.2 with the generated key.
microheart status Print running (pid N) or stopped.
microheart console [-n 40] Show the last lines of the guest console.
microheart down Stop the VM and remove the TAP device and NAT rule.

Global options (before the command): --rootfs FILE, --key FILE, --vcpu N (default 1), --mem MIB (default 256).

Python API

from microheart import MicroVM

with MicroVM("alpine.ext4", "vm_key", vcpu=2, mem_mib=512) as vm:
    print(vm.ssh("uname -a").stdout)
Member Meaning
MicroVM(rootfs, key, vcpu=1, mem_mib=256, tap="tap0", run_dir=None) Describe a VM. Nothing starts yet.
.start(wait=60) Boot. Return the seconds until SSH worked. Needs root.
.stop() Ask the guest to reboot (Firecracker then exits). Kill it after 10 s.
.clean() stop() plus remove the TAP device and NAT rule.
.ssh(cmd, check=True, timeout=30) Run a command in the guest. Return subprocess.CompletedProcess.
.running(), .pid() State of the Firecracker process.
.machine_config() Read /machine-config from the Firecracker API.
.tail(n) Last n console lines.

How it works

  1. assets.py finds the Firecracker binary and kernel (bundled, then cache, then download).
  2. net.py makes tap0 with host IP 172.16.0.1/30, turns on IP forwarding and adds MASQUERADE.
  3. vm.py writes vm_config.json and starts firecracker --config-file ... --enable-pci.
  4. The guest MAC 06:00:AC:10:00:02 and the disk's /etc/network/interfaces give the guest 172.16.0.2/30 with gateway 172.16.0.1. DNS (8.8.8.8) is written at boot.
  5. microheart polls SSH until the guest answers.

Network layout:

guest eth0 172.16.0.2/30 <--virtio--> host tap0 172.16.0.1/30 --NAT--> host default interface --> internet

One VM at a time for now: the IP addresses and tap0 are fixed.

Root disk recipe

src/microheart/data/ holds the recipe:

  • Dockerfile: Alpine 3.20, OpenRC, OpenSSH, iproute2, curl. SSH is key-only.
  • files/: network config, DNS at boot, serial console options.
  • build-rootfs.sh: Docker image to folder, add your public key, mkfs.ext4 -d, e2fsck.

Edit the recipe to add your own packages, then run build-rootfs again.

Security notes

  • The serial console asks for a login, and root has no password, so you cannot log in on the console. Use SSH (microheart ssh). Use microheart console to read boot messages.
  • SSH accepts keys only. The key is made on your machine and is never part of the package.
  • The guest can reach the internet through host NAT. The guest and host FORWARD policy is set to ACCEPT.
  • Firecracker's jailer (extra isolation) is not used yet.
  • microheart runs as root and changes host network settings. Read the code first.

Limits and roadmap

  • Alpha, untested on a real host.
  • One VM at a time (fixed addresses).
  • No snapshots, no jailer, no multi-VM networking.
  • Planned: per-VM addresses, --config-file options, snapshots, jailer support, aarch64 tests.

Development

See CONTRIBUTING.md. Build a wheel with the binary and kernel inside:

python scripts/bundle.py && python -m build --wheel
wheel tags --platform-tag manylinux_2_17_x86_64 --remove dist/*.whl

License

MIT, see LICENSE. Third-party software (Firecracker: Apache-2.0; Linux kernel: GPL-2.0) is downloaded or bundled unchanged. See NOTICE.

Metadata

Release files for microheart 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for microheart 0.1.2
File Size Uploaded
microheart-0.1.2.tar.gz 16.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for microheart 0.1.2
File Interpreter ABI Platform
microheart-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 32.0 kB

Release files / microheart-0.1.2.tar.gz

Download URL microheart-0.1.2.tar.gz
Size 16.2 kB
Tags Source
SHA-256 checksum
How to use checksums
d15ee2330950a37a11d6ede858841ddc535795062cee0ed71c830db677a3e423
BLAKE2b-256 checksum
How to use checksums
d0075140cc1314b0ea991ae030cd436bf41c56c1da20f5df1897395d2da3ab71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release files / microheart-0.1.2-py3-none-any.whl

Download URL microheart-0.1.2-py3-none-any.whl
Size 15.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6353127053f5e66903e7860b8c2d7891c59c34f2a6c723f2fb3dff6d9a3dc382
BLAKE2b-256 checksum
How to use checksums
1656c84ea10ef45e886b2cb4a11593b6dd41b3ccb1a27b75d624ad8cf8f5633b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 18, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.2 This release

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page