Understanding the system's journey from pressing the power button to services running: BIOS/UEFI, GRUB, kernel, initramfs, to systemd. Completed with how to manage kernel modules, sysctl parameters, and troubleshooting when boot goes wrong.

After episode 15 where we covered Storage Management, LVM, and Filesystem — how disks are partitioned, combined into logical volumes, and formatted into a ready-to-use filesystem — you now know how data is stored physically. But have you ever asked: where does this whole system "come alive"? What happens between pressing the power button and the login terminal appearing?
That journey is called the boot process — and it's where the Linux kernel works the hardest before handing control over to systemd. Understanding this process isn't just academic knowledge. When a production server won't wake up after a maintenance window, or when you mischange a kernel parameter and the machine won't boot, this understanding decides whether you can rescue the system in minutes or are forced to rebuild from scratch.
In this episode 16, we'll trace every boot stage — from firmware, bootloader, kernel, initramfs, to systemd. Then we'll step into the world of the kernel itself: modules that can be loaded and removed like puzzle pieces, and the runtime parameters you can change via sysctl. By the end of the episode, you'll have a clear roadmap to diagnose and fix boot problems.
The Linux boot process can be divided into several major stages. Imagine the boarding process for an airplane: someone powers up, someone arranges the luggage, someone starts the engines, and only after all the checks are complete does the plane take off. Linux does the same, strictly and in order.
Power On
│
▼
1. Firmware (BIOS/UEFI) ── POST, hardware check, select boot device
│
▼
2. Bootloader (GRUB) ── show menu, select kernel & parameters
│
▼
3. Kernel ── decompress, initialize CPU/memory/core drivers
│
▼
4. initramfs ── mount the root filesystem, load needed drivers
│
▼
5. systemd (PID 1) ── run targets & service units
│
▼
6. Login prompt / services ready to useStage 1 — Firmware (BIOS/UEFI). Before any operating system, there's firmware embedded in the motherboard. BIOS (legacy) or UEFI (modern) performs a Power-On Self-Test (POST), recognizes basic hardware, then looks for a boot device. Key difference: BIOS reads the disk's first sector directly, while UEFI loads an EFI file living on a special partition called the EFI System Partition (ESP, usually /dev/sda1 with a FAT32 filesystem).
Stage 2 — Bootloader (GRUB). GRUB (GRand Unified Bootloader) is the bridge between firmware and kernel. Its job is to show the boot menu, find the kernel stored on the disk, then jump to it. GRUB stores its configuration in /boot/grub/grub.cfg — but this file must not be edited directly; instead it's generated from /etc/default/grub and the scripts in /etc/grub.d/.
Stage 3 — Kernel. The Linux kernel is the core program decompressed into memory that begins initializing the most fundamental things: the interrupt table, CPU scheduler, and memory management. At this point the kernel can't fully access the root filesystem because its drivers aren't necessarily available yet.
Stage 4 — initramfs. This is where one of the most misunderstood concepts sits. The Initial RAM filesystem is a small filesystem loaded into RAM alongside the kernel. Its contents are the drivers and tools needed to find and mount the actual root disk — for example NVMe drivers, LVM drivers, or LUKS encryption drivers. The analogy: the kernel is a pilot who needs a co-pilot (initramfs) to set navigation before handing the plane over to the full system.
Stage 5 — systemd. After the root filesystem is successfully mounted, systemd takes over as PID 1 — the first process that will become the "mother" of all other processes. systemd doesn't run all services at once; it follows a hierarchy of targets, which we'll discuss shortly.
Note
Remember these three key terms so you don't confuse them: the kernel is the core program managing hardware; the initramfs is the temporary filesystem that helps the kernel find the root disk; and systemd is the init system that runs services after the full system is ready. This order can't be swapped.
Before the systemd era, boot ran through rigid runlevels 0–6. systemd replaced them with targets — logical units that are a collection of services and their dependencies. To read the boot order in systemd: follow the default.target.
systemctl get-default
systemctl list-units --type=target --state=activesystemctl list-dependencies default.targetThe result will show a chain: default.target → multi-user.target (or graphical.target) → basic.target → sysinit.target → ... down to the most basic units. This order is guaranteed by a dependency graph, so systemd can parallelize services that don't depend on each other — one of the reasons modern Linux boots far faster than its predecessors.
To change the target run at boot, use:
systemctl set-default multi-user.target
systemctl get-defaultAll boot choices — which kernel is used, what parameters are given — are controlled by GRUB. The main configuration file you may edit is /etc/default/grub:
GRUB_DEFAULT=0
GRUB_TIMEOUT=5
GRUB_DISTRIBUTOR="$(sed 's, release .*$,,g' /etc/system-release)"
GRUB_CMDLINE_LINUX="rhgb quiet"
GRUB_DISABLE_RECOVERY="true"The two variables you'll touch most often:
| Variable | Function | Example |
|---|---|---|
GRUB_DEFAULT | The boot entry selected by default | 0, 1, or saved |
GRUB_TIMEOUT | How long the menu shows before auto-boot (seconds) | 5, 10 |
GRUB_CMDLINE_LINUX | Kernel parameters added to all entries | "quiet", "selinux=0" |
GRUB_CMDLINE_LINUX_DEFAULT | Parameters for normal (non-recovery) boot entries | "quiet splash" |
After changing this file, you must regenerate the GRUB configuration. The command name differs between distros — one of the classic traps:
sudo update-grubWarning
Forgetting to run update-grub after editing /etc/default/grub is the most common mistake in the GRUB world. Your configuration appears changed in the file, but at reboot GRUB still reads the old grub.cfg. Always regenerate, then verify with grep menuentry /boot/grub/grub.cfg.
Recovery Mode & Single-User Mode. When the system fails to boot due to a problematic service or a lost root password, you can enter emergency modes:
rescue.target and provides a menu to repair packages, run fsck, or enter a root shell.systemd.unit=rescue.target or init=/bin/bash) — a minimal boot with no network services, just one root shell. This is your last "wrench".How to: in the GRUB menu, press e to edit the boot entry, then add systemd.unit=rescue.target at the end of the line starting with linux. Press Ctrl+X to boot.
linux /vmlinuz-... root=/dev/mapper/vg-root ro systemd.unit=rescue.targetCaution
Single-user mode gives a root shell without authentication to anyone who can press buttons on the physical console. On datacenter servers, make sure the physical console and out-of-band management (iLO/iDRAC/IPMI) are access-protected. Never leave a console open and unattended.
After a successful boot, let's get to know the running kernel. The first commands you must memorize:
uname -r # kernel version
uname -m # CPU architecture (x86_64, aarch64)
uname -a # all concise informationExample uname -r output:
6.8.0-31-genericReading 6.8.0-31-generic means: kernel series 6.8, patchlevel 0, and build .31 from the Ubuntu distro with the generic flavour. When a problem relates to hardware, this kernel version is what you mention in forums or when filing a bug report.
Kernel Logs with dmesg. The kernel talks via dmesg — a ring buffer containing messages since system boot. This is the first window into hardware problems:
sudo dmesg | tail -20sudo dmesg | grep -iE "error|fail|oom"sudo dmesg -T | tail -20Kernel logs are also stored permanently in /var/log/kern.log (Debian/Ubuntu) or inside the journal: journalctl -k. To investigate the last boot, journalctl -b is your best friend — discussed in detail in episode 14 about systemd & journal.
The Linux kernel is designed modularly — not all drivers are loaded permanently; instead they're modules that can be loaded and removed as needed. Think of a laptop whose supports are installed when needed and unplugged when done, without turning the laptop off.
| Command | Function |
|---|---|
lsmod | Show currently loaded modules |
modinfo <module> | Module details: version, license, dependencies, description |
modprobe <module> | Load a module along with its dependencies |
modprobe -r <module> | Remove a module |
ls /lib/modules/$(uname -r) | Directory containing all modules for this kernel |
Let's practice. For example the nf_tables module used by the nftables firewall:
lsmod | grep nf_tablesmodinfo nf_tablessudo modprobe nf_tablesTo load a module permanently at boot, don't write it to rc.local or an init script — use a file in /etc/modules-load.d/:
tunThe tun module (above) is very important for OpenVPN and network tunneling — a topic aligned with the later networking episodes. After the file is created, the module will load automatically at the next boot.
Tip
Before adding a module to /etc/modules-load.d/, test it first with modprobe then check lsmod. If the module doesn't exist in the /lib/modules/$(uname -r) directory, it means the module isn't available for your kernel — usually because the linux-modules-extra package isn't installed or the kernel is too old.
sysctl: Changing Kernel Behavior Without RebootingKernel runtime parameters are stored as text files in /proc/sys. The tool that makes them easy to read and change is sysctl. This is the modern way to configure behaviors like IP forwarding (so a machine can become a router), TCP tuning, and protection against SYN flood attacks.
sysctl net.ipv4.ip_forwardsudo sysctl -w net.ipv4.ip_forward=1Changes with sysctl -w only last until reboot. To make them permanent, write to /etc/sysctl.d/ — files with sequence numbers execute first:
net.ipv4.ip_forward = 1sudo sysctl --system/proc/sys can be read directly like a normal file — for example cat /proc/sys/net/ipv4/ip_forward. The directory hierarchy in /proc/sys exactly mirrors the sysctl parameter names: dots (.) replace slashes (/).
Here are the traps that most often make servers fail to boot or make the kernel "pout":
1. Forgetting update-grub after changing GRUB. Already discussed — changes in /etc/default/grub don't take effect until grub.cfg is regenerated. It often happens when you remove a kernel parameter or change the timeout.
2. Adding a wrong kernel parameter causes boot to hang at the kernel stage. The solution: reboot, in the GRUB menu press e, remove the suspicious parameter from the linux line, then boot. Invalid parameters usually make the kernel fall into a kernel panic before the login prompt appears.
3. Initramfs out of sync with the kernel. When you upgrade the kernel or move to a new one, the initramfs must be rebuilt. Distros generally do this automatically via hooks (Debian/Ubuntu) or dracut (RHEL), but if you move the root filesystem to a new LVM (a continuation of episode 15) and forget to run mkinitrd/dracut --force, the system will fail to find the root disk:
sudo update-initramfs -u -k allsudo dracut --force --regenerate-all4. Debugging cryptic kernel panics. Note the last line of the panic — it usually contains the problematic module or driver, for example Kernel panic - not syncing: Attempted to kill init! or a failure on the nouveau driver. Use dmesg from a safe session or single-user mode to diagnose.
5. Running modprobe -r on a module still in use. The kernel will refuse with Module is in use or it will break functionality. First check with lsmod | grep <module> whether any process is using the module.
In this episode 16, you've assembled a complete roadmap of the Linux boot journey: from the firmware (BIOS/UEFI) that powers on the machine, GRUB that selects the kernel, the kernel that initializes the system core, initramfs that finds the root disk, to systemd as PID 1 that starts targets and services. You also learned to manage kernel modules with lsmod, modprobe, and modinfo, adjust runtime kernel behavior via sysctl in /proc/sys, and rescue the system via recovery mode and single-user mode.
Key points to take home:
/etc/default/grub, then always run update-grub (Debian) or grub2-mkconfig (RHEL) — there's no shortcut.uname -r for kernel identity, dmesg for kernel health, journalctl -k for the permanent record.modprobe, made persistent via /etc/modules-load.d/.sysctl -w and permanently via /etc/sysctl.d/.In the next episode 17 we'll step out of the machine and start communicating with other machines via the topic Networking Fundamentals & Diagnostic Tools. We'll dismantle ip addr, ip route, ping, traceroute, DNS lookup, and ss for checking open ports — the mandatory foundation before you take on SSH, firewalls, and network services in the following episodes. See you there!