Skip to content
ALB Wiki

LFS Kernel and Boot

This is an old revision of this page — revision 8 (2026-10-26 13:02:06 UTC). It may differ from the current revision.

This is the chapter where it boots. The fifty-package marathon leaves a complete userspace sitting on a partition — but a filesystem is not a machine. Chapter 6 installs the last load-bearing pieces (the boot scripts, the fstab, the network config, the kernel itself, the bootloader), and then commits the ultimate act: rebooting into the system you built. If it comes up, you own a Linux assembled entirely from source — every binary a product of your own compiler.

First: the configuration files

Before kernel, before GRUB — the system's identity files. Inside the chroot:

# /etc/fstab — what mounts where at boot
cat > /etc/fstab << "EOF"
# file system  mount-point  type   options          dump  fsck order
/dev/sda3      /            ext4   defaults         1     1
/dev/sda2      none         swap   pri=1            0     0
proc           /proc        proc   nosuid,noexec,nodev 0 0
sysfs          /sys         sysfs  nosuid,noexec,nodev 0 0
devpts         /dev/pts     devpts gid=5,mode=620   0     0
tmpfs          /run         tmpfs  defaults         0     0
devtmpfs       /dev         devtmpfs mode=0755,nosuid 0   0
tmpfs          /dev/shm     tmpfs  nosuid,nodev     0     0
cgroup2        /sys/fs/cgroup cgroup2 nosuid,noexec,nodev 0 0
EOF
# UEFI builders add:  /dev/sda1  /boot/efi  vfat  ...

And the network — iproute2 + a static or dhcpcd config in /etc/sysconfig/, plus /etc/resolv.conf if DNS is static:

cat > /etc/sysconfig/ifconfig.eth0 << "EOF"
ONBOOT=yes
IFACE=eth0
SERVICE=ipv4-static
IP=192.168.1.20
GATEWAY=192.168.1.1
PREFIX=24
BROADCAST=192.168.1.255
EOF
cat > /etc/resolv.conf << "EOF"
nameserver 192.168.1.1
EOF
hostname > /etc/hostname

Plus /etc/inittab (for SysVinit — defining the runlevels and the gettys), /etc/sysconfig/clock, /etc/inputrc, /etc/shells, and the sysklogd config. The book walks each; every one is a file you've been meaning to understand — now you write them from nothing.

The kernel — configuration as authorship

cd /sources/linux-*/
make mrproper
make defconfig      # a sane generic starting point
make menuconfig     # YOUR hardware, YOUR choices — the real work

menuconfig is the chapter's soul: an ncurses tree of every kernel option — CPU family, filesystems, device drivers, security modules. The rules of thumb:

  • Built-in [*] vs module [M]: disk controllers and root filesystem must be built-in (a module can't load before the filesystem it lives on mounts — unless you carry an initramfs; classic LFS builds them in)
  • Your disk controller — SATA/AHCI (CONFIG_ATA, SATA_AHCI), NVMe (CONFIG_BLK_DEV_NVME), or virtio (CONFIG_VIRTIO_*) for QEMU — must be in
  • Your filesystem — CONFIG_EXT4_FS built-in
  • Your network card — e1000e, virtio-net, whatever the machine has
  • Devtmpfs automount — CONFIG_DEVTMPFS_MOUNT=y so /dev populates itself at boot
  • UEFI — CONFIG_EFI + EFI_VARS if you're on it

Then compile — the longest single build of the project:

make -j$(nproc)
make modules_install
cp -iv arch/x86_64/boot/bzImage /boot/vmlinuz-<ver>-lfs-12.x
cp -iv System.map /boot/System.map-<ver>
cp -iv .config /boot/config-<ver>
install -d /usr/share/doc/linux-<ver>
cp -r Documentation/* /usr/share/doc/linux-<ver>

The three files in /boot are the kernel (bzImage), its symbol map (System.map), and the recipe it was built from (.config — keep it; every future kernel starts from it).

GRUB — the door

On BIOS/MBR:

grub-install /dev/sda
cat > /boot/grub/grub.cfg << "EOF"
set default=0
set timeout=5
insmod part_msdos       # part_gpt on GPT-partitioned BIOS disks
insmod ext2
set root=(hd0,3)
menuentry "GNU/Linux, Linux <ver>-lfs" {
  linux /vmlinuz-<ver>-lfs-12.x root=/dev/sda3 ro
}
EOF

On UEFI/GPT: grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=LFS and the ESP mounted at /boot/efi — root=/dev/sda3 unchanged. GRUB's (hd0,3) partition numbering starts at 1; root= is the kernel's view. Getting these two right — and matching them — is the chapter's most classic mistake.

The kernel config — the critical set

The options that decide whether it boots:

# make menuconfig — the load-bearing options:
CONFIG_EXT4_FS=y                 # root filesystem — BUILT-IN not module
CONFIG_ATA + SATA_AHCI=y         # SATA disks — or:
CONFIG_BLK_DEV_NVME=y            # NVMe — or:
CONFIG_VIRTIO_BLK/PCI=y          # QEMU virtio — VM builds
CONFIG_DEVTMPFS=y + DEVTMPFS_MOUNT=y   # /dev populates itself at boot
CONFIG_VT=y + VT_CONSOLE=y       # the virtual console — or nothing displays
CONFIG_EFI=y + EFI_VARS=y        # UEFI builds
CONFIG_NET + your NIC driver=y   # networking
CONFIG_TMPFS=y                   # /run, /dev/shm
CONFIG_PROC_FS + SYSFS=y         # /proc /sys — the kernel interfaces
CONFIG_UNIX=y                    # unix sockets — EVERYTHING needs this
CONFIG_BINFMT_ELF=y              # run ELF binaries — or nothing runs

The pattern: boot-critical = built-in [*], everything else = module [M] or off [ ]. A module can't load from a filesystem that isn't mounted — disk + rootfs + console must be built-in, or you carry an initramfs to load them early. LFS's classic path: build them in, no initramfs — simpler.

The fstab in full

cat > /etc/fstab << "EOF"
# device         mount    type    options                    dump pass
/dev/sda3        /        ext4    defaults                   1    1
/dev/sda2        none     swap    pri=1                      0    0
proc             /proc    proc    nosuid,noexec,nodev        0    0
sysfs            /sys     sysfs   nosuid,noexec,nodev        0    0
devpts           /dev/pts devpts  gid=5,mode=620             0    0
tmpfs            /run     tmpfs   defaults                   0    0
devtmpfs         /dev     devtmpfs mode=0755,nosuid          0    0
tmpfs            /dev/shm tmpfs   nosuid,nodev               0    0
cgroup2          /sys/fs/cgroup cgroup2 nosuid,noexec,nodev  0    0
EOF
# UEFI adds:  /dev/sda1  /boot/efi  vfat  defaults  0  2

The dump/pass columns: pass 1 = fsck checks root first, 2 = after, 0 = never. The virtual filesystems mount nosuid,nodev,noexec — kernel interfaces shouldn't run code.

The network's files

cat > /etc/sysconfig/ifconfig.eth0 << "EOF"
ONBOOT=yes
IFACE=eth0
SERVICE=ipv4-static
IP=192.168.1.20
GATEWAY=192.168.1.1
PREFIX=24
BROADCAST=192.168.1.255
EOF
cat > /etc/resolv.conf << "EOF"
nameserver 192.168.1.1
EOF
echo "lfs" > /etc/hostname
cat > /etc/hosts << "EOF"
127.0.0.1 localhost lfs
::1       localhost
EOF

GRUB — both paths

BIOS/MBR:

grub-install /dev/sda          # writes to the boot sector — the disk, not a partition
cat > /boot/grub/grub.cfg << "EOF"
set default=0
set timeout=5
insmod part_msdos   # or part_gpt for GPT
insmod ext2
set root=(hd0,3)              # GRUB numbering: disks 0-based, partitions 1-based
menuentry "GNU/Linux, Linux 6.x-lfs" {
  linux /vmlinuz-6.x-lfs root=/dev/sda3 ro
}
EOF

UEFI/GPT:

mkfs.vfat /dev/sda1          # the ESP — if not already
mount /dev/sda1 /boot/efi    # mount the ESP
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=LFS
# grub.cfg identical — GRUB-EFI reads it the same

The two numbering traps: GRUB's (hd0,3) is disk 0, partition 3 (0-indexed disks, 1-indexed partitions); the kernel's root=/dev/sda3 is Linux naming. They must match — same partition, two languages.

The boot's transcript — reading it

A successful first boot scrolls: GRUB's menu → Loading Linux 6.x → Loading initial ramdisk (or none — LFS classic has none) → kernel decompress → the device-detection flood → Freeing unused kernel memory → Run /sbin/init as init process → the init scripts' [ OK ]-style output → login:. Each stage's failure signature is the troubleshooting table's input.

The moment of truth

# exit the chroot, unmount the virtual filesystems
exit
umount -v $LFS/dev/pts
umount -v $LFS/{sys,proc,run,dev}
umount -v $LFS
reboot

Boot. GRUB's menu appears; the kernel decompresses; init starts; login prompts on a console. login: root — into a system where every single file is something you compiled. uname -a, cat /etc/lfs-release, ls / — a filesystem of your own making.

The inittab — SysVinit's boot map

cat > /etc/inittab << "EOF"
id:3:initdefault:          # default runlevel — multiuser text
si::sysinit:/etc/rc.d/init.d/rc S sysinit   # system init

l0:0:wait:/etc/rc.d/init.d/rc 0     # halt
l1:S1:wait:/etc/rc.d/init.d/rc 1    # single-user
l2:2:wait:/etc/rc.d/init.d/rc 2
l3:3:wait:/etc/rc.d/init.d/rc 3     # multiuser — the default
l4:4:wait:/etc/rc.d/init.d/rc 4     # X11
l5:5:wait:/etc/rc.d/init.d/rc 5
l6:6:wait:/etc/rc.d/init.d/rc 6     # reboot

ca::ctrlaltdel:/sbin/shutdown -t5 -r now   # Ctrl-Alt-Del

# the gettys — the login prompts, one per virtual console:
1:2345:respawn:/sbin/agetty --noclear tty1 9600
2:2345:respawn:/sbin/agetty tty2 9600
3:2345:respawn:/sbin/agetty tty3 9600
4:2345:respawn:/sbin/agetty tty4 9600
5:2345:respawn:/sbin/agetty tty5 9600
6:2345:respawn:/sbin/agetty tty6 9600

su:S06:once:/sbin/sulogin     # single-user mode prompt
EOF

Each line is id:runlevels:action:command — initdefault picks runlevel 3, sysinit runs the system-init script first, respawn restarts gettys forever (so a logged-out console re-prompts), ctrlaltdel handles the three-finger salute. telinit 1 drops to single-user; telinit 6 reboots.

The bootscripts — the rc chain

/etc/rc.d/init.d/ holds the service scripts — rc runs them per runlevel through rc.d/rcS.d/, rc.d/rc3.d/ etc. (S = start links, K = kill). The LFS book ships lfs-bootscripts — a minimal set: checkfs (fsck on boot), cleanfs, modules (load kernel modules), mountvirt (the virtual filesystems), network, sysklogd, sendsignals, reboot, halt. Each is a readable shell script — the SysV virtue: cat shows the entire boot plan.

What almost always goes wrong — and what to do

SymptomCause
Kernel panic: "unable to mount root fs"Disk controller or ext4 built as module not built-in — rebuild kernel with [*]
GRUB can't find the kernelset root=(hd0,N) numbering vs actual partition — enumerate with ls at GRUB's command line
Boots but no networkNIC driver missing — make menuconfig, add it built-in
Boots but no console/keyboardCONFIG_VT, keyboard driver missing
/dev empty at bootDEVTMPFS_MOUNT off — rebuild
GRUB error: no such partitionGPT vs MBR mismatch — insmod part_gpt or wrong root
Boots into GRUB rescue onlygrub-install targeted the wrong disk
Everything works except the hostname/etc/hostname or hosts file

The recovery move you'll need

If it won't boot: boot the host/live system again, mount /dev/sda3 /mnt/lfs, re-mount the virtual filesystems, chroot back in — the whole chapter-4 pivot — fix the kernel config or grub.cfg, and reboot again. LFS's greatest lesson: nothing is unrecoverable while the host still boots. The chroot door works both directions.

What you now own

A Linux where ls /usr/bin is a list of things you built — where gcc --version reports a compiler you compiled, where the kernel's .config is your hardware autographed. The system is minimal — no X, no package manager, no convenience — but it's complete: it boots, logs in, runs jobs, and can compile more of itself.

Exercises

  1. Boot it. (The only exercise that matters.)
  2. Read your kernel's .config — find the five options that would have prevented boot had they been modules.
  3. Rebuild the kernel with one deliberate break (e.g. ext4 as M) — watch the panic, then chroot-rescue it back.
  4. Write the fstab from memory; compare to the book's.
  5. df -h / — how big is the system you built?

Timeline

StepResult
Config filesfstab, inittab, network, hostname
Kernel configYour hardware, autographed into .config
Kernel buildbzImage + System.map + .config in /boot
GRUBThe bootloader installed and written
RebootThe machine runs itself
nextBLFS — X, tools, the usable system beyond the base

References

  • linuxfromscratch.org — chapters 9–10: system configuration, kernel, bootloader
  • Hosted mirror: /dist/books/ — the official LFS book mirrored on this site (v10.0–13.1, SysV + systemd editions; CC BY-NC-SA 2.0 / MIT, hosted verbatim with attribution)
  • The kernel's own Kconfig documentation — make menuconfig's reference
  • GRUB manual — boot-time partition/device naming

See also

Categories: Handbook · LFS · Linux · Linux Handbook
This page was last edited 2026-10-26 13:02:06 UTC by devin. What links here