Overview & Prerequisites

This section is the on-ramp, and it is the first gate. Before you read a single line of vstate/vcpu/ or trace a PUT /boot-source from a Unix socket down to a KVM_RUN exit, you need a Linux host with working hardware virtualization, a Firecracker checkout that builds with tools/devtool, a microVM that boots from your own binary, and a git identity wired for DCO sign-off. This page gets you there. Budget two to four hours for a cold setup — most of that is the first Docker image pull and the first cargo build compiling the dependency tree.

This curriculum will not hold your hand. It assumes you are a strong systems/backend engineer who can read unfamiliar Rust without a guide, who is comfortable with processes, threads, file descriptors, mmap, ioctl, epoll, and Unix sockets. What it will do is point you at the exact parts of the codebase that matter, give you the right questions, and make you prove competence at each gate. The setup below is the first such gate: if you cannot build Firecracker and boot a microVM from your own binary, nothing else in the curriculum will work.


The One Hard Requirement: Linux + KVM + Hardware Virtualization

Firecracker is Linux-only, runs on x86_64 or aarch64, and is built directly on KVM. There is no macOS build, no Windows build, no "emulation fallback." If you are reading this on a Mac or a Windows box (as many of you are), you need a Linux host with a real /dev/kvm to do the work.

KVM needs CPU virtualization extensions exposed to it: Intel VT-x / VMX or AMD-V / SVM on x86_64, or EL2 + stage-2 translation on aarch64. The kernel must have the kvm and kvm_intel/kvm_amd (or arm64 equivalent) modules loaded, and your user must be able to read and write /dev/kvm.

# THE single most important pre-flight check. If this fails, nothing else works.
ls -l /dev/kvm
# crw-rw---- 1 root kvm 10, 232 ... /dev/kvm   ← you must be able to read+write it

# Are you allowed to use it? Either be in the `kvm` group or have rw access another way.
[ -r /dev/kvm ] && [ -w /dev/kvm ] && echo "KVM OK" || echo "NO KVM ACCESS — fix this first"

# Add yourself to the kvm group if needed (then log out / back in):
sudo usermod -aG kvm "$(whoami)"

# Is hardware virtualization actually available to the CPU?
grep -Eoc '(vmx|svm)' /proc/cpuinfo   # x86_64: nonzero = HW virt present
lscpu | grep -i virtualization        # human-readable

Warning — nested virtualization and bare metal. A laptop or a desktop running Linux on bare metal "just works." A cloud VM usually does not, because the guest VM lacks /dev/kvm unless nested virtualization is enabled. On AWS, Firecracker development is done on bare-metal (*.metal) instances — ordinary EC2 instances cannot run it. On GCP/Azure, enable nested virt on the instance. Locally, a Linux VM under VMware/VirtualBox/QEMU needs "Expose VT-x/AMD-V to guest" turned on. If ls -l /dev/kvm fails inside your dev VM, you are on the wrong kind of host.

Tip: A Linux desktop or laptop you already own is the smoothest path. Second-best is a *.metal cloud instance. WSL2 on Windows has /dev/kvm on recent builds and can work, but bare-metal Linux is the reference experience the rest of this curriculum assumes.


What You Are Setting Up (the whole picture)

┌──────────────────────────────────────────────────────────────────────────────┐
│  Your Linux host  (x86_64 or aarch64, /dev/kvm present and writable)          │
│                                                                              │
│   Docker  ── tools/devtool runs the build/test INSIDE a pinned container ──┐  │
│      │        public.ecr.aws/firecracker/fcuvm:vNN  (Rust toolchain,       │  │
│      │        cross-compilers, test kernels, pytest harness)               │  │
│      ▼                                                                      │  │
│   ~/src/firecracker  ◄── git clone ── github.com/firecracker-microvm/...    │  │
│      │                                                                      │  │
│      │  tools/devtool build  (bind-mounts the source into the container)    │  │
│      ▼                                                                      │  │
│   build/cargo_target/<arch>-unknown-linux-musl/<debug|release>/firecracker  │  │
│      │   + jailer                                                           │  │
│      ▼                                                                      │  │
│   sudo ./firecracker --api-sock /tmp/fc.sock   ── one process = one microVM │◄─┘
│      ▲   │                                                                  │
│      │   │  ioctl() on /dev/kvm  (KVM_CREATE_VM, KVM_RUN, …)                │
│   curl --unix-socket /tmp/fc.sock  PUT /boot-source /drives /actions …      │
│                                                                            │
│   git commit -s  ──►  DCO Signed-off-by  ──►  PR on GitHub (≥2 approvals)   │
└──────────────────────────────────────────────────────────────────────────────┘

Three facts shape everything:

  1. Firecracker builds inside a Docker dev container driven by tools/devtool. You do not install a Rust toolchain system-wide; the container pins the exact channel (from rust-toolchain.toml), carries the cross-compilers and the test kernels, and bind-mounts your source. You need Docker, Git, and a checkout — that is essentially it.
  2. One Firecracker process is exactly one microVM. There is no daemon managing many VMs. You start the process with an API socket, configure the machine by PUT-ing JSON over that socket, then send InstanceStart. Density at scale comes from running many Firecracker processes.
  3. Contribution happens on GitHub — issues and pull requests against main on github.com/firecracker-microvm/firecracker. There is no CLA. Every commit needs a DCO sign-off (git commit -s), and merging requires two maintainer approvals.

Step 1 — Install the toolchain

ToolVersionWhy
Dockerrecenttools/devtool runs the entire build/test inside a container. The one tool you truly cannot skip.
Git2.xClone, branch, sign off commits, push to your fork.
curlanyDrive the API on the Unix socket — your primary "user" interface.
rustup / cargomatches rust-toolchain.toml (e.g. 1.96.0, verify on your branch)Optional for the container build, but you want it locally for rust-analyzer, cargo doc, and editor navigation.
An editor with rust-analyzerlatestNavigation across the vmm/firecracker/jailer crates is the highest-leverage skill here.
ripgrep (rg)anyThis curriculum locates code with rg, never line numbers. Install it.
# Verify the essentials.
docker --version        # any recent Docker
git --version           # git version 2.x
curl --version          # any recent curl
rg --version            # ripgrep — used constantly below

# Confirm Docker can run (the build needs this to work without sudo, ideally).
docker run --rm hello-world

Note: You do not need a specific system Rust version to build Firecracker — the dev container pins it. But install rustup and let it pull the channel named in rust-toolchain.toml so your editor's rust-analyzer and any local cargo doc use the same compiler the CI does. Mismatches here cause confusing "works in CI, red in my editor" noise.

Tip: Add yourself to the docker group (sudo usermod -aG docker "$(whoami)", then re-login) so tools/devtool does not need sudo. The build runs the container as your UID and writes the output back into your checkout; running it as root muddies file ownership.


Step 2 — Clone the repo and read its contract

mkdir -p ~/src && cd ~/src
git clone https://github.com/firecracker-microvm/firecracker.git
cd firecracker

# Confirm you are on the development line and see recent history.
git branch -a | head
git log --oneline -5

Read these files in the repo root before you build anything — they are the project's own contract with you. Confirm they exist, then actually read them:

cd ~/src/firecracker
ls CONTRIBUTING.md CHANGELOG.md SPECIFICATION.md FAQ.md SECURITY.md MAINTAINERS.md CHARTER.md
ls docs/getting-started.md docs/jailer.md docs/seccomp.md docs/prod-host-setup.md
FileRead it for
CONTRIBUTING.mdThe DCO sign-off rule, the ≥2-approval policy, the tools/devtool checks expected before a PR, commit hygiene (one logical change per commit, ≤72-char title), the integration-test requirement.
docs/getting-started.mdThe canonical "get a kernel + rootfs and boot a microVM" walkthrough. Your Step 4 below follows it.
SPECIFICATION.mdWhat Firecracker is and deliberately is not — the minimal-device-model contract.
CHANGELOG.mdThe convention you will add an entry to in every functional PR. Also tells you which features landed when (your anti-staleness anchor).
SECURITY.mdVulnerabilities go privately to AWS Security, never as public issues.
MAINTAINERS.md / CHARTER.mdWho can approve/merge, and the single-vendor governance model.

Warning: The first tools/devtool build pulls a multi-gigabyte Docker image and compiles the entire dependency tree. Do it on a good connection and expect 15–40 minutes the first time. Subsequent builds reuse the image and cargo's incremental cache and are far faster.


Step 3 — First build with tools/devtool

tools/devtool is the front door to everything. It wraps cargo build (via tools/release.sh) inside the pinned container, defaulting the C library to musl for a static binary.

cd ~/src/firecracker

# See what devtool can do — read this once.
tools/devtool --help

# First build. Default profile is debug; default libc is musl.
tools/devtool build

# A release build (optimized; what you want for any timing/perf observation).
tools/devtool build --release
# Equivalent control over the C library if you ever need glibc:
#   tools/devtool build --release -l gnu

The binaries land under build/cargo_target/, keyed by target triple and profile. Locate them rather than assuming a path — the arch segment differs on aarch64 (verify on your branch):

# Find your freshly built firecracker + jailer — run this, don't trust a hard-coded path.
find build/cargo_target -maxdepth 3 -type f \( -name firecracker -o -name jailer \)
# x86_64 release example:
#   build/cargo_target/x86_64-unknown-linux-musl/release/firecracker
#   build/cargo_target/x86_64-unknown-linux-musl/release/jailer

# Confirm the binary runs and report its version.
FC=$(find build/cargo_target -type f -name firecracker | grep -E 'release|debug' | head -1)
"$FC" --version

While the build runs, learn the quality gates you will live by — they are exactly what reviewers run:

tools/devtool fmt           # cargo fmt + clippy --fix + cargo sort + python/markdown formatters
tools/devtool checkstyle    # style checks (no code changes)
tools/devtool checkbuild --all   # builds every target/feature combination the CI builds

Note: Clippy runs warnings-as-errors in CI: cargo clippy --all --all-targets --all-features -- -D warnings. A PR with a single clippy warning will not pass. CONTRIBUTING.md recommends wiring tools/devtool checkstyle and checkbuild --all as git hooks so you never push a build that CI will reject. Full walkthrough in Lab 1.1 and Lab 1.2.

Warning: The integration suite is pytest, in tests/, driven by tools/devtool test — not raw cargo test. Unit tests are cargo test, but the suite that actually gates a PR is Python. Do not assume cargo test alone proves your change.


Step 4 — Boot a microVM (the smoke test that proves the build)

This is the moment the whole thing becomes real. You need two artifacts: an uncompressed kernel (vmlinux) and a root filesystem (a flat ext4 image). docs/getting-started.md shows how to fetch CI artifacts from the spec.ccfc.min bucket (a vmlinux-X.Y.Z and an Ubuntu squashfs converted to a ~1 GiB ext4). Follow it to land ./vmlinux and ./rootfs.ext4 next to your binary, then:

FC=$(find build/cargo_target -type f -name firecracker | grep release | head -1)
API=/tmp/firecracker.socket
rm -f "$API"

# 1. Start the VMM. It does nothing yet but listen on the socket.
sudo "$FC" --api-sock "$API" &

# 2. Point it at a kernel + the kernel command line.
curl -X PUT --unix-socket "$API" \
  --data '{"kernel_image_path":"./vmlinux","boot_args":"console=ttyS0 reboot=k panic=1"}' \
  http://localhost/boot-source

# 3. Give it a root filesystem (exposed as a virtio-block device).
curl -X PUT --unix-socket "$API" \
  --data '{"drive_id":"rootfs","path_on_host":"./rootfs.ext4","is_root_device":true,"is_read_only":false}' \
  http://localhost/drives/rootfs

# 4. (Optional) size the machine. Defaults: vcpu_count=1, mem_size_mib=128, smt=false.
curl -X PUT --unix-socket "$API" \
  --data '{"vcpu_count":2,"mem_size_mib":1024}' http://localhost/machine-config

# 5. Start the microVM. The kernel boots; you get a login prompt on the serial console.
curl -X PUT --unix-socket "$API" \
  --data '{"action_type":"InstanceStart"}' http://localhost/actions

If a Linux boot log scrolls past in the terminal where you launched Firecracker and you reach a login prompt, your build works and your KVM access is correct. That is the gate. The full guided version, with serial-console capture and teardown, is Lab 1.3, and the Warm-Up takes this much further (networking, a second drive, snapshots, MMDS).

Tip: Default microVM is 1 vCPU / 128 MiB. To shut a running microVM down cleanly, send {"action_type":"SendCtrlAltDel"} to /actions (x86_64), or reboot from inside the guest with reboot=k on the cmdline. Killing the Firecracker process also works — it owns the whole microVM.


Step 5 — Configure Git for DCO sign-off

Firecracker requires a Developer Certificate of Origin sign-off on every commit. This is not a CLA — it is a one-line Signed-off-by: trailer asserting you have the right to contribute the code. A DCO bot fails any PR with an unsigned commit.

# The identity in your Signed-off-by line MUST match the GitHub account/email you contribute from.
git config --global user.name  "Your Real Name"
git config --global user.email "you@example.com"

# Sign off every commit with -s. This appends:
#   Signed-off-by: Your Real Name <you@example.com>
git commit -s -m "net: fix off-by-one in RX descriptor accounting"

# Forgot -s on the last commit? Amend it.
git commit --amend -s --no-edit

# Forgot it across a range? Re-sign them all.
git rebase --signoff HEAD~3

A correctly signed commit message ends with:

net: fix off-by-one in RX descriptor accounting

Signed-off-by: Your Real Name <you@example.com>

Warning: The name/email in Signed-off-by: must match your git identity exactly and be an email GitHub recognizes for your account. Mismatches fail the DCO check and force you to rewrite history. Also keep commits clean: one logical change per commit, each commit passing tests, title ≤72 chars. Reviewers will ask you to split a "fix three things" commit.

The fork-and-pull flow (fork on GitHub, push a branch, open a PR against main) is covered in Level 2 and the PR quality chapter. For now, just get your local identity and sign-off working — this is part of the gate.


Step 6 — Join the community

Firecracker is developed in the open but single-vendor governed: a dedicated AWS team maintains it, with no separate foundation or steering committee and no GOVERNANCE.md. Get plugged in now.

ChannelWhereUse it for
GitHub accounthttps://github.comIssues, PRs, code review — the entire contribution flow.
Issues listhttps://github.com/firecracker-microvm/firecracker/issuesFind work, read triage, study how maintainers reason.
Maintainer emailfirecracker-maintainers@amazon.comThe public contact list for project questions and coordination.
Security reportsAWS Security (private; see SECURITY.md)Vulnerabilities — never open a public issue for a security bug.
CHANGELOG / releasesCHANGELOG.md, GitHub ReleasesTrack what landed and when; anchor your "(verify on your branch)" checks.

Learn the labels you will use constantly (verify the exact set on the repo):

LabelMeaning
good first issueScoped, well-defined starter work — where you begin in Level 2.
Type: Bug / Type: EnhancementThe nature of the issue.
Status: Awaiting review / Status: ...Where an issue/PR sits in the workflow.
Priority: ...Triage urgency.
KaniFormal-verification work (the Kani model checker).
Roadmap: ...Items tied to the public roadmap.

Note: Large designs live as GitHub issues and discussion, not in a wiki. Reading how a feature was argued into existence (or rejected) on a thread is the single best way to absorb the project's values — especially the minimal-device-model philosophy, where "QEMU has it" is explicitly not an argument. The design-via-github chapter builds this skill.


How the Curriculum Fits Together

The curriculum is 9 levels of core engineering, several supporting tracks, and a capstone. Work the levels top to bottom — each builds directly on the previous, and the labs depend on foundations laid earlier.

flowchart TD
    L1[Level 1: Virtualization & Firecracker Foundation] --> L2[Level 2: Contributor Onboarding]
    L2 --> L3[Level 3: Architecture & the Threading Model]
    L3 --> L4[Level 4: KVM, vCPUs & the Run Loop]
    L4 --> L5[Level 5: Testing & Debugging]
    L5 --> L6[Level 6: The Boot Process & Guest Memory]
    L6 --> L7[Level 7: The Virtio Device Model]
    L7 --> L8[Level 8: Real Issue Contribution]
    L8 --> L9[Level 9: Advanced Maintainer]
    L9 --> CAP[Capstone: one full contribution cycle]

    RV[rust-vmm: the crates beneath FC] -.referenced by.-> L1
    RV -.-> L4
    RV -.-> L7
    DD[Deep Dives x26] -.-> L3
    DD -.-> L4
    DD -.-> L6
    DD -.-> L7
    DD -.-> L9
    MIND[Contributor Mindset] -.-> L2
    MIND -.-> L8
    ISS[Issue Roadmap: 12 stages] -.-> L2
    ISS -.-> L8
    ENG[Engineering at Scale] -.-> L9
    MC[Feature Masterclasses x8] -.-> L7
    MC -.-> L9
    INT[Cross-Repo & Integration Labs] -.-> L8
    GOV[Release, Review & Governance] -.-> L9
    CAP --> GOV
TrackWhat it isWhen you touch it
Levels 1–9The spine. Sequential. Each level has 2–4 labs.Work top to bottom; do not skip.
Contributor MindsetHow to read the codebase, design via GitHub, handle feedback, grow toward maintainership.Alongside Levels 2, 8, 9.
Issue Roadmap12 staged issue difficulties, docs/tests → release-blocking.Pick real issues as you progress.
Internals Deep Dives (26)Focused internals chapters, each with a reading exercise and a "common bugs" table.Open the relevant one whenever a level references it.
rust-vmmThe shared crates (kvm-ioctls, vm-memory, linux-loader, …) Firecracker is built on, with hands-on labs.Throughout; heavily in Levels 1, 4, 7.
Engineering at ScaleReal design problems: snapshotting, oversubscription, I/O engines, boot-time.Level 9 and the capstone.
Feature Masterclasses (8)Deep intensives: KVM, boot, virtio, snapshots, security, networking, debugging, performance.When you want to go past a level's depth.
Integration Labsfirecracker-containerd, the jailer in production, the Go SDK, bug attribution.Around Level 8.
Release & GovernanceSingle-vendor governance, release policy, licensing, building trust.Level 9 and the capstone.
CapstoneA complete real contribution: issue → reproduction → root cause → fix → tests → PR → write-up.The final phase.

The deep dives and the rust-vmm section are not optional reading — they are where the real depth lives. A level says "trace a virtio-block I/O"; the virtio-block deep dive and the virtqueues deep dive are where you learn how the descriptor chain actually works. Treat the levels as the spine and the deep dives as the muscle.


How to Use the Labs

Every lab follows the same shape, so you always know where you are:

  • Background and Why This Lab Matters for Contributors — the why before the how.
  • Prerequisites — what must already work (usually a green build and a prior lab).
  • Step-by-Step Tasks — numbered, with real tools/devtool / curl --unix-socket / git / rg commands and expected output.
  • Deliverables — checkboxes you must satisfy.
  • Troubleshooting, Expected Output, Stretch Goals.
  • Validation / Self-check — 5–7 questions that gate completion.

Rules for the labs:

  1. Run every command. This is a hands-on apprenticeship; reading is not doing.
  2. When a lab gives an rg/find, run it rather than trusting a line number. Firecracker's layout has shifted (a big refactor merged several crates into vmm), so the curriculum points you at code with commands instead of fabricated lines. If a path differs on your branch, the rg still finds it.
  3. Do not advance past a lab's Validation section until you can answer it without notes.
  4. Treat "(verify on your branch)" literally. Where this curriculum cites a version-sensitive fact (a default, an endpoint, a layout constant), confirm it against your checkout and CHANGELOG.md before relying on it.

You Are Ready When…

Confirm every box before opening Level 1:

  • ls -l /dev/kvm shows a device you can read and write; grep -Ec '(vmx|svm)' /proc/cpuinfo is nonzero (or you are on aarch64 with EL2).
  • docker run --rm hello-world works without sudo.
  • ~/src/firecracker is cloned and you have read CONTRIBUTING.md, docs/getting-started.md, and skimmed SPECIFICATION.md.
  • tools/devtool build --release produced a firecracker (and jailer) under build/cargo_target/.../release/, and firecracker --version runs.
  • tools/devtool checkstyle passes on a clean checkout.
  • You booted a microVM (a kernel log scrolled and you reached a login prompt).
  • git config user.name/user.email are set and git commit -s adds a Signed-off-by: line.
  • You have a GitHub account, have skimmed the issues list and its labels, and know that security reports go privately to AWS Security.
# A 5-minute "am I ready" smoke test (run from ~/src/firecracker).

# 1. Host can do hardware virtualization and you can touch /dev/kvm.
ls -l /dev/kvm && { [ -r /dev/kvm ] && [ -w /dev/kvm ] && echo "KVM rw OK"; }
grep -Ec '(vmx|svm)' /proc/cpuinfo

# 2. Your build exists and runs.
FC=$(find build/cargo_target -type f -name firecracker 2>/dev/null | head -1)
echo "binary: ${FC:-NOT BUILT — run tools/devtool build}"
[ -n "$FC" ] && "$FC" --version

# 3. Style gate is green and git is wired for DCO.
tools/devtool checkstyle 2>&1 | tail -3
git config user.name && git config user.email

# 4. Prove a microVM boots (after Step 4 artifacts are in place):
#    re-run the Step 4 curl sequence and watch for a guest login prompt.

If any box is unchecked, fix it now. A broken baseline means every later tools/devtool build, every curl --unix-socket, and every boot attempt will produce confusing failures that hide the real work.


Where to Go Next

  • The Hitchhiker's Guide to Virtualization, KVM & microVMs — read this before Level 1. It builds the mental model from first principles: trap-and-emulate, the KVM ioctl API, the three jobs of a VMM, the vCPU run loop, how a kernel boots with no BIOS, and virtio in one page.
  • Firecracker Warm-Up: From User to Contributor — the most important page in this section. Run Firecracker as a user across five real scenarios, then bridge each one to the source.
  • 16-Week Plan — a calendar that maps Levels 1–9 + supporting tracks + capstone onto 16 weeks, with reading, labs, GitHub-issue practice, and exit checkpoints.
  • Milestones: M1–M9 — the competence gates. Each has skills, self-check questions, and a 20-point rubric.

Continue to the Hitchhiker's Guide, then the Warm-Up, and only then start Level 1: Virtualization and Firecracker Foundation.