Booting a Linux MicroVM in Firecracker (and Why You Should Care)

Once upon a time, virtual machines were heavy, slow, and bloated. Then came containers — fast and light, but they shared the host kernel. Firecracker slices through that compromise. It’s a lightweight virtual machine monitor (VMM) designed for launching thousands of minimal, secure microVMs with near-instant startup.

This tutorial walks through a minimal Firecracker setup to boot a Linux VM. No Docker, no Kubernetes, no YAML — just you, a kernel, and a handful of syscalls.


🧱 The Basics First

Imagine you’re building a tiny house (a microVM) inside a secure garage (your Linux system). You need:

  • A blueprint (the kernel)
  • A floorplan and storage (the root filesystem)
  • Tools to build it (Firecracker binary)
  • Permission to use the space and tools (KVM access)

🧰 Prerequisites

  • Linux host with KVM support (/dev/kvm should exist). You may need to turn on virtualisation in either the BIOS (if you are running bare metal) or in your virtualisation host, e.g. in VirtualBox you need to turn on Settings/System/Processor/Enable Nested VT-x/AMD-V.
  • Root or sudo privileges.
  • curl, unzip, and basic CLI tools.
  • A static build of the Linux kernel.
  • An initramfs (we’ll use BusyBox for simplicity).

🔽 Step 1: Download Firecracker

  1. Visit the latest release page:
    👉 github.com/firecracker-microvm/firecracker/releases/latest

  2. Look under “Assets”, and find the binary for your platform.
    Example: firecracker-v1.7.0-x86_64

  3. Copy the direct download URL from that page, then download it using curl (The version numbers will be different in your own setup!):

1
2
curl -L -o firecracker https://github.com/firecracker-microvm/firecracker/releases/download/v1.12.1/firecracker-v1.12.1-x86_64.tgz
tar -xvf firecracker-v1.12.1-x86_64.tgz

Then change directory to the newly created firecracker release directory (the name will vary depending on the version), and run this (again, the version numbers may be different).

1
2
cd release-v1.12.1-x86_64/
sudo cp firecracker-v1.12.1-x86_64 /usr/local/bin/firecracker

🐧 Step 2: Get a Linux Kernel

1
curl -LO https://s3.amazonaws.com/spec.ccfc.min/img/hello/kernel/hello-vmlinux.bin

You can also compile your own with make defconfig && make -j$(nproc).


📦 Step 3: Get a Root Filesystem

1
curl -LO https://s3.amazonaws.com/spec.ccfc.min/img/hello/fsfiles/hello-rootfs.ext4

This is a minimal rootfs with BusyBox. Enough to get a shell inside the VM.


⚙️ Step 4: Create a Firecracker Configuration

Create a file named boot_config.json:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
{
  "boot-source": {
    "kernel_image_path": "hello-vmlinux.bin",
    "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
  },
  "drives": [
    {
      "drive_id": "rootfs",
      "path_on_host": "hello-rootfs.ext4",
      "is_root_device": true,
      "is_read_only": false
    }
  ]
}

🚀 Step 5: Start Firecracker

1
sudo firecracker --api-sock /tmp/firecracker.socket

Leave this terminal running. It should say:

1
2
3
Running Firecracker vX.Y.Z
Listening on API socket ("/tmp/firecracker.socket")
API server started.

What it does:

You’re launching the Firecracker engine, but not yet building anything. It’s just waiting for instructions, like a quiet worker in the garage.

The --api-sock is how you talk to it — a special Unix socket file (a local communication pipe).

Note that if you terminate this with Ctrl-C the socket may stay open (and you will get an error if you try to run firecracker again). In this case type this to clean up the leftover socket:

1
sudo rm -f /tmp/firecracker.socket

🧪 Step 6: In a second terminal, configure the microVM

Note that in the first two commands below, the paths to hello-vmlinux.bin and hello-rootfs.ext4 must be the correct absolute paths that match your own installation (i.e. where you saved those files). You can find the whole path using:

1
realpath hello-vmlinux.bin 

🔹 Set up the kernel (boot source)

1
2
3
4
5
6
7
8
sudo curl --unix-socket /tmp/firecracker.socket -i \
  -X PUT http://localhost/boot-source \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "kernel_image_path": "/home/simon/git/firecracker-first-boot/hello-vmlinux.bin",
    "boot_args": "console=ttyS0 reboot=k panic=1 pci=off"
  }'

Expected response: HTTP/1.1 204

What it does:

You’re handing Firecracker a blueprint — the Linux kernel it will use to boot the microVM. kernel_image_path points to the kernel binary file.
boot_args are like startup instructions (e.g. use a serial console, don’t reboot on panic, etc.).


🔹 Attach the root filesystem

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sudo curl --unix-socket /tmp/firecracker.socket -i \
  -X PUT http://localhost/drives/rootfs \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "drive_id": "rootfs",
    "path_on_host": "/home/simon/git/firecracker-first-boot/hello-rootfs.ext4",
    "is_root_device": true,
    "is_read_only": false
  }'

Expected response: HTTP/1.1 204

What it does:

You’re giving your microVM a hard drive — a pre-built file system image that it can boot into.


🔹 Start the VM

1
2
3
4
5
6
7
sudo curl --unix-socket /tmp/firecracker.socket -i \
  -X PUT http://localhost/actions \
  -H "Accept: application/json" \
  -H "Content-Type: application/json" \
  -d '{
    "action_type": "InstanceStart"
  }'

Expected response: HTTP/1.1 204

What it does:

You tell Firecracker to turn the key and start the microVM.

  • Firecracker uses KVM to create a virtual CPU
  • Loads the kernel you gave it
  • Mounts the root filesystem
  • Starts the system like a tiny, self-contained Linux box

But Why All the Curl Commands?
Firecracker is controlled through a REST API over a Unix socket, like talking to a local server. Instead of a GUI or CLI, you send HTTP-style instructions using curl.


🖥️ Step 7: Watch the VM boot in the first terminal

You should see something like:

1
2
3
localhost login: root
Password: 
Welcome to Alpine!

For the kernel we downloaded here, the username and password are both root.

You are now inside your Firecracker microVM!

✅ Done! You’ve successfully booted a Linux microVM using Firecracker with no Docker, no Kubernetes, no YAML — just syscalls and a shell.

You can run this to see the Linux version:

1
cat /etc/os-release

🧼 Cleanup

Kill Firecracker:

1
sudo pkill firecracker

Unmount any mounted volumes if needed:

1
2
ls /tmp/firecracker.socket
sudo rm -f /tmp/firecracker.socket

🧠 What Just Happened?

You booted a fully isolated Linux microVM using Firecracker — without Docker, without a hypervisor GUI, and with near-zero overhead. This is what powers AWS Lambda, Fargate, and other serverless platforms behind the scenes.


🪵 Next Steps

  • Try building your own rootfs with BusyBox
  • Add networking support using TAP interfaces
  • Explore snapshotting and performance tuning

Firecracker is a scalpel, not a Swiss Army knife. If you care about deep isolation, fast startup, and minimalism, it’s worth getting to know.