Appendix B: Guest Kernels And Root Filesystems
Firecracker starts with two guest artifacts: a kernel image and, unless the kernel contains an initramfs, a root filesystem. They are one boot contract. The kernel must use a format the loader understands, discover the selected virtio transport, include the root device and filesystem drivers, and find a userspace init that can remain PID 1.
This appendix describes that contract. It does not provide a universal kernel config or distribution recipe. Both depend on the Firecracker release, CPU architecture, transport, devices, and userspace being shipped.
Building a kernel does not require
/dev/kvmor root privileges. Booting the result does. Keep Firecracker runs on a bare-metal Linux host or in a VM with nested virtualization. The image commands below overwrite the named image file; use a scratch path and check it before running them.
Start With The Support Policy
Firecracker continuously validates combinations drawn from its supported host
and guest kernel tables. As of Firecracker source commit
fb53569b807c8e1349e4d2b49d5300e463a91d73, the guest table is:
| Page Size | Guest Kernel | First Firecracker Release | Minimum Support Date |
|---|---|---|---|
| 4K | 5.10 | 1.0.0 | 2024-01-31 |
| 4K | 6.1 | 1.9.0 | 2026-09-02 |
The last column is a minimum end-of-support date, not an automatic removal date. A version remains supported while it remains in the current table. Check the policy for the Firecracker release being deployed rather than inferring support from the calendar.
The repository also contains 6.18 guest config files for both architectures, but the guest support table does not list 6.18. Their presence is not, by itself, a support declaration.
Choose The Transport First
Firecracker creates virtio devices on MMIO by default. Starting Firecracker
with --enable-pci instead creates all virtio devices on the PCI transport.
This is a machine-wide choice, not a per-device setting.
| Transport | Kernel Configuration | Boot Command Line |
|---|---|---|
| MMIO | CONFIG_VIRTIO_MMIO=y and each required device driver |
Firecracker appends pci=off when PCI is disabled |
| PCI | CONFIG_PCI=y, CONFIG_PCI_MMCONFIG=y, CONFIG_PCI_MSI=y, CONFIG_PCIEPORTBUS=y, CONFIG_BLK_MQ_PCI=y, CONFIG_VIRTIO_PCI=y |
Must not contain pci=off |
On aarch64, PCI also needs CONFIG_PCI_HOST_COMMON=y and
CONFIG_PCI_HOST_GENERIC=y. On x86_64, CONFIG_PCI=y is also required for the
ACPI boot path even when the devices themselves use MMIO.
Do not confuse transport with device type. CONFIG_VIRTIO_MMIO or
CONFIG_VIRTIO_PCI lets Linux reach a virtio device; CONFIG_VIRTIO_BLK,
CONFIG_VIRTIO_NET, and the other device-specific options let Linux drive it.
Anything needed before the root filesystem is mounted must be built in with
=y, unless an initramfs supplies the module and loads it first.
Build The Boot Path
Firecracker's policy gives the following minimal starting points. A useful kernel normally adds logging, the selected transport, the root filesystem driver, and any devices the workload actually uses.
| Boot Source | Architecture | Policy Minimum |
|---|---|---|
| Initrd | x86_64 | CONFIG_BLK_DEV_INITRD=y, CONFIG_KVM_GUEST=y |
| Initrd | aarch64 | CONFIG_BLK_DEV_INITRD=y, CONFIG_VIRTIO_MMIO=y |
| Root block device | x86_64 | CONFIG_VIRTIO_BLK=y, CONFIG_ACPI=y, CONFIG_PCI=y, CONFIG_KVM_GUEST=y |
| Root block device | aarch64 | CONFIG_VIRTIO_BLK=y |
For an ext4 root image, add CONFIG_EXT4_FS=y. A kernel that must locate a
partition by PARTUUID also needs the relevant partition parser; Firecracker's
policy names CONFIG_MSDOS_PARTITION. For useful serial diagnostics, enable
CONFIG_SERIAL_8250_CONSOLE=y and CONFIG_PRINTK=y.
The rest follows the configured devices:
| Function | Built-In Options |
|---|---|
| Network | CONFIG_VIRTIO_NET=y |
| Vsock | CONFIG_VIRTIO_VSOCKETS=y |
| Entropy device | CONFIG_HW_RANDOM_VIRTIO=y |
| Balloon | CONFIG_MEMORY_BALLOON=y, CONFIG_VIRTIO_BALLOON=y |
| Hotplugged memory | CONFIG_VIRTIO_MEM=y |
| Persistent memory | CONFIG_VIRTIO_PMEM=y |
These are conditional requirements, not a checklist for every guest. For example, a guest with no vsock device does not need the vsock driver. The same rule applies to filesystems, security modules, and network protocols: derive the config from the actual guest contract.
On x86_64, CONFIG_KVM_GUEST=y enables KVM-aware guest support, including the
KVM clock dependency in the supported configurations. Firecracker's clean
shutdown path also uses CONFIG_SERIO_I8042=y and
CONFIG_KEYBOARD_ATKBD=y. On aarch64, the policy calls out
CONFIG_ARM_AMBA=y, CONFIG_RTC_DRV_PL031=y, and
CONFIG_SERIAL_OF_PLATFORM=y for time and serial support.
Treat The CI Configs As Coupled Artifacts
resources/guest_configs/ contains base configs for aarch64 and x86_64 at
5.10, 6.1, and 6.18, plus an x86_64 5.10 no-ACPI variant. The directory also
contains ci.config, debug.config, and ftrace.config overlays.
Those files are evidence of what Firecracker CI builds; they are not generic
upstream Linux configs. The kernel policy says they are used with Amazon Linux
microvm-kernel-* trees, which can contain required backports, and explicitly
does not guarantee that the configs produce usable images from the equivalent
upstream kernel.
For an exact CI artifact, use Firecracker's documented build entry point from a checked-out release:
./tools/devtool build_ci_artifacts kernels 6.1
This is a resource-intensive repository build, not a host configuration step.
For a custom upstream kernel, begin with the target tree's architecture config,
select options from the boot contract above, run make olddefconfig, and
inspect the resulting .config. Copying a same-numbered Firecracker config
across kernel trees skips the compatibility question that matters most.
The CI configs are deliberately narrow. They disable modules and many hardware
subsystems, and their DISCLAIMER.md describes them as optimized for
high-density, ephemeral workloads. Review their security, filesystem, namespace,
debugging, and observability choices against the workload instead of assuming
that smaller means production-ready.
Produce The Loader Artifact
The output differs by architecture:
| Architecture | Build Target | Firecracker Artifact |
|---|---|---|
| x86_64 | make vmlinux |
Uncompressed ELF vmlinux |
| aarch64 | make Image |
PE-formatted arch/arm64/boot/Image |
On x86_64, Firecracker's ELF loader uses the PVH entry when the image contains
the corresponding note; CONFIG_PVH=y is present in the 6.1 CI config. The
loader otherwise follows its Linux boot-protocol path. Do not substitute
arch/x86/boot/bzImage for the documented uncompressed ELF artifact.
On aarch64, Firecracker uses its PE loader for Image. The 6.1 CI config
contains CONFIG_EFI=y and CONFIG_EFI_STUB=y, which produce the expected
image form; this does not turn the microVM into a general EFI firmware
environment.
Understand Discovery And Boot Arguments
With x86_64 ACPI boot, Firecracker describes the machine in ACPI tables. The
legacy no-ACPI path instead describes virtio-MMIO devices with
virtio_mmio.device= command-line entries and requires
CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y. Firecracker's policy deprecates that
legacy mechanism. On aarch64, the device tree supplies the MMIO layout.
If the API request omits boot_args, current Firecracker starts from:
reboot=k panic=1 nomodule 8250.nr_uarts=0 i8042.noaux i8042.nomux i8042.dumbkbd swiotlb=noforce
A supplied boot_args value replaces that default. Firecracker still augments
the resulting line for its configured machine: it adds pci=off when PCI is
disabled and derives root=/dev/vda or root=PARTUUID=..., plus ro or rw,
from the root block drive. A root pmem device similarly becomes
root=/dev/pmemN. Do not add a second root= argument when the API already
marks a drive as the root device.
Add a console argument appropriate to the guest if logs must be visible. The
common x86_64 choice is console=ttyS0; aarch64 early-console requirements
differ by kernel config. A silent guest is not evidence that the kernel did not
run.
Define The Root Filesystem Contract
A root image needs more than a filesystem signature. Before building it, answer four questions:
- Which block transport and filesystem drivers are built into the kernel?
- Which executable will become PID 1?
- Is that executable static, or are its interpreter and shared libraries present?
- Which paths must remain writable after the root is mounted?
Linux first tries /init for an initramfs. For the final root it honors an
init= override, then any configured default, then tries /sbin/init,
/etc/init, /bin/init, and /bin/sh. Failure to execute any candidate ends
in a kernel panic. A successful PID 1 must perform the initialization the guest
needs and must not simply exit.
At minimum, a conventional root tree supplies the chosen init and its runtime
dependencies, plus mount points such as /dev, /proc, /sys, /run, and
/tmp. CONFIG_DEVTMPFS=y lets the kernel provide device nodes;
CONFIG_DEVTMPFS_MOUNT=y can mount devtmpfs automatically when the kernel
mounts the final root directly. An initramfs or custom init may need to mount it
explicitly.
Preserve numeric ownership, modes, symlinks, extended attributes, and file
capabilities while assembling the tree. Those are part of the guest's security
boundary. A read-only root also needs writable tmpfs mounts or data volumes for
state such as /run, temporary files, logs, and application data.
Build Ext4 Without Mounting It
mke2fs -d copies an existing directory into a newly created filesystem. It
avoids loop mounts and root privileges, which makes the artifact boundary
easier to audit:
truncate -s 256M rootfs.ext4
mke2fs -t ext4 -d rootfs-tree rootfs.ext4
e2fsck -fn rootfs.ext4
The first two commands create or overwrite rootfs.ext4; verify that name and
run them only in a scratch artifact directory. rootfs-tree must be a prepared
directory, not a tar archive. The final command performs a read-only check.
This method does not solve provenance. Construct rootfs-tree from pinned
packages or reproducible build outputs, keep a manifest, and scan the finished
artifact. If a distribution-specific tool requires containers, mounts, loop
devices, or root, run that workflow in an isolated build VM and treat the
result as untrusted until validated.
Validate The Pair
Before booting, inspect the artifacts independently:
- Confirm the kernel file format and architecture with
fileandreadelf. - Save the final
.config, kernel source revision, toolchain version, and build command beside the image. - Use
debugfsor another read-only ext filesystem inspector to confirm init, its interpreter and libraries, directory modes, ownership, and symlinks. - Run
e2fsck -fnagainst the finished ext4 image. - Compare the enabled virtio transport and device drivers with the Firecracker machine configuration.
- Record the exact
boot_argsand the root-drive settings that will augment them.
Only the final boot test needs KVM. Run it in the isolated virtualization host, capture the serial log, and keep the tested kernel, rootfs, Firecracker binary, and configuration as one versioned set.