Kernel Configuration
The Problem
FortrOS builds multiple kernel images for different stages of the boot chain. Each has different requirements: the bootstrapper needs to run on unknown hardware, the preboot needs to be small and fast, and the node kernel needs virtualization and storage features. Getting kernel config wrong is silent -- the kernel compiles fine but fails on hardware it doesn't have drivers for, or includes drivers that waste memory and boot time.
Three Kernels, Three Strategies
Bootstrapper Kernel: Maximum Compatibility
The bootstrapper runs once on unknown hardware. It PXE boots, downloads the preboot, writes it to disk, and reboots. It never runs again. The priority is: boot on everything, ask questions never.
Start from a distro's "generic" or "server" config (Alpine LTS, Debian, Fedora) and strip what's clearly unnecessary (sound, graphics acceleration, exotic filesystems). Keep everything else. The cost of extra drivers is a larger kernel (~15MB vs ~8MB) and slightly slower boot (~1s). The cost of a missing driver is a bricked provisioning session.
Must have:
- All common NIC drivers: Intel (e1000, e1000e, igb, igc), Realtek (r8169), Broadcom (tg3, bnx2), USB ethernet (asix, cdc_ether, r8152)
- All common storage: AHCI, NVMe, USB mass storage, virtio-blk (for VPS provisioning)
- Display: EFI framebuffer (efifb), VESA framebuffer (vesafb), simpledrm, framebuffer console. The admin needs to see what's happening.
- USB: XHCI, EHCI, OHCI (for USB keyboards, YubiKeys, USB ethernet)
- WiFi: iwlwifi, ath9k, ath10k (for laptop provisioning)
- Basics: kexec, DHCP (via busybox), EFI stub, ACPI, PCI, PCIe
Nice to have:
- Netconsole (remote printk over UDP for debugging)
- EFI earlycon (display output before framebuffer initializes)
Don't need:
- KVM/virtualization (bootstrapper doesn't host VMs)
- dm-crypt/LUKS (bootstrapper doesn't encrypt anything)
- WireGuard (bootstrapper uses TLS, not overlay network)
- CRDTs, gossip (bootstrapper is not an org member)
- Confidential computing (SEV-SNP, TDX)
Preboot Kernel: Lean and Secure
The preboot runs on known hardware classes (the org knows what nodes it has). It boots from the ESP, authenticates to the org, unlocks /persist, and kexecs into the node kernel. It runs for seconds, not hours.
Start from a minimal config and add what's needed. The preboot kernel should be as small as possible to:
- Fit in the UKI on the ESP (with initramfs)
- Boot fast (every second in preboot is a second the node isn't working)
- Minimize attack surface (preboot holds sensitive keys in memory)
Must have:
- NIC drivers for org's hardware: only what's deployed, not everything. A homelab with all Intel NICs only needs e1000e. A mixed fleet adds r8169.
- WiFi: the preboot needs network to reach the org for auth. A laptop on WiFi-only needs iwlwifi/ath* in the preboot. WiFi credentials come from UEFI vars (saved by main OS on previous boot) or a captive portal flow. Without WiFi, a laptop can't authenticate on cold boot away from the org's LAN.
- Storage: whatever the org uses (NVMe, AHCI, virtio for VPS)
- LUKS/dm-crypt: unlock /persist
- TPM 2.0: read/write preboot_secret and signing key
- kexec: hand off to node kernel
- KHO (6.19+): preserve memory across kexec
- EFI stub: boot from ESP
- PCI MSI: required for cloud-hypervisor VMs
- USB: XHCI, EHCI (YubiKey for hibernate resume, USB ethernet fallback)
Don't need:
- Sound, GPU acceleration, Bluetooth
- KVM, VFIO (preboot doesn't host VMs)
Node Kernel: Full Featured
The node kernel runs the actual workloads. It needs everything the node's role requires. This is the kernel that stays running for days/weeks.
Start from the preboot config and add:
- KVM: VM hosting (cloud-hypervisor uses KVM)
- VFIO/IOMMU: device passthrough (GPU, NVMe to VMs)
- WireGuard: overlay network
- dm-thin: shard + scratch storage pools
- cgroup v2: container isolation
- Namespaces: container isolation
- SEV-SNP/TDX: confidential computing (if hardware supports it)
- Netfilter: iptables/nftables for VM networking
The node kernel can also be optimized for the specific CPU architecture
via localmodconfig after the first boot (Phase 2-3 in the roadmap).
Derivation Strategy
Bootstrapper: Start from a Distro Config
Don't hand-roll. Take a known-working distro config that boots on the widest range of hardware:
# Get Alpine's LTS config (known to boot on most x86_64 hardware)
wget alpine-lts-config
# Or Debian's generic config
# Or Fedora's server config
# Strip what bootstrapper doesn't need
scripts/config --disable SOUND
scripts/config --disable DRM_I915 # GPU acceleration
scripts/config --disable DRM_AMDGPU
scripts/config --disable XFS # exotic filesystems
scripts/config --disable BTRFS
scripts/config --disable NFS_FS
# Ensure what it DOES need
scripts/config --enable KEXEC
scripts/config --enable EFI_STUB
scripts/config --enable FB_EFI
scripts/config --enable FRAMEBUFFER_CONSOLE
scripts/config --enable E1000E
scripts/config --enable R8169
scripts/config --enable VIRTIO_NET
scripts/config --enable VIRTIO_BLK
# Resolve dependencies
make olddefconfig
The result is a large (~15MB) but universally compatible kernel. This is correct for a one-time bootstrapper.
Preboot and Node: Build Up from Minimal
Start from tinyconfig or defconfig and add only what's needed:
make tinyconfig
# Add architecture basics
scripts/config --enable 64BIT
scripts/config --enable SMP
scripts/config --enable EFI
scripts/config --enable EFI_STUB
scripts/config --enable ACPI
scripts/config --enable PCI
scripts/config --enable PCI_MSI
# Add specific drivers for org's hardware
scripts/config --enable E1000E # if org uses Intel NICs
scripts/config --enable NVME # if org uses NVMe
# ... etc
make olddefconfig
Hardware Probe Informs Config
The bootstrapper runs a hardware probe on first boot. The probe output tells the org what drivers the preboot and node kernels need for this specific machine. Future preboot/node images can be built with only the necessary drivers, reducing size and attack surface.
Bootstrapper boots on unknown Dell Optiplex
-> probes: Intel I219-LM NIC, NVMe SSD, SATA HDD, Intel UHD 630 GPU
-> reports to org: needs e1000e, nvme, ahci, i915 (for GPU passthrough)
-> org builds preboot with: e1000e, nvme, ahci (lean)
-> org builds node with: e1000e, nvme, ahci, i915, kvm, vfio (full)
Kconfig Silent Drops
Kconfig silently drops options whose dependencies aren't met. This is the
most common source of "kernel compiles fine but doesn't work" bugs. For
example, CONFIG_PCI_MSI=y requires CONFIG_PCI=y. If PCI isn't enabled,
MSI is silently removed during make olddefconfig.
The build system should verify after every kernel build that no explicitly
set option was dropped. See verify_kconfig() in buildroot/build.sh.
Links
- BIOS Settings -- Firmware settings that affect kernel behavior
- 01 Power and Firmware -- Boot chain overview
- TPM -- TPM driver requirements
- KVM -- Virtualization requirements for node kernel