Table of Contents
- Pre-Boot: BIOS/UEFI Initialization
- Bootloader: Loading the Kernel
- Kernel Initialization & Initramfs
- systemd Takes Over: The “Init” Phase
- Key systemd Stages: Units, Targets, and Dependencies
- Post-Boot: User Session & Beyond
- Troubleshooting the Boot Process
- Conclusion
- References
1. Pre-Boot: BIOS/UEFI Initialization
The boot process begins before the operating system (OS) even loads—with firmware-level initialization. Modern systems use either BIOS (Basic Input/Output System) or UEFI (Unified Extensible Firmware Interface) for this step.
BIOS vs. UEFI: What’s the Difference?
- BIOS: Legacy firmware found in older systems. It initializes hardware, runs the POST (Power-On Self-Test), and selects a boot device (e.g., HDD, SSD, USB). It has limited features (e.g., no support for disks larger than 2.2 TB) and uses the MBR (Master Boot Record) partition scheme.
- UEFI: Modern replacement for BIOS. It offers faster boot times, support for large disks (via GPT partition tables), secure boot (prevents unsigned code from loading), and a graphical interface for configuration. Most new systems use UEFI.
Key Steps in BIOS/UEFI:
- POST (Power-On Self-Test): Checks critical hardware (CPU, RAM, storage, keyboard) for errors. If a failure is detected (e.g., no RAM), the system emits beep codes or displays an error.
- Boot Device Selection: After POST, the firmware scans configured boot devices (order set in BIOS/UEFI settings) and loads the bootloader from the first valid device (e.g., an SSD with Linux installed).
2. Bootloader: Loading the Kernel
Once the firmware hands off control, the bootloader takes over. Its job is to locate and load the Linux kernel and an initial RAM filesystem (initramfs) into memory. The most common bootloader for Linux is GRUB (Grand Unified Bootloader) (v2, specifically GRUB2).
GRUB2: The Default Bootloader
GRUB2 is flexible and supports multiple OSes (e.g., dual-booting Linux and Windows). Here’s how it works:
- Stage 1: Stored in the MBR (BIOS) or EFI System Partition (ESP, for UEFI). Its only job is to load the next stage (Stage 1.5 or 2).
- Stage 2: Loaded from the
/boot/grubdirectory. It parsesgrub.cfg(the main configuration file) to display a boot menu (e.g., “Ubuntu”, “Advanced options for Ubuntu”). - Kernel Selection: When you choose an OS from the menu, GRUB2 loads the kernel (e.g.,
vmlinuz-5.15.0-78-generic) and initramfs (e.g.,initrd.img-5.15.0-78-generic) into RAM.
Example GRUB2 Configuration Snippet (/boot/grub/grub.cfg):
menuentry 'Ubuntu' --class ubuntu {
recordfail
load_video
gfxmode $linux_gfx_mode
insmod gzio
insmod part_gpt
insmod ext2
set root='hd0,gpt2' # Boot device (e.g., first disk, second partition)
linux /vmlinuz-5.15.0-78-generic root=/dev/sda2 ro quiet splash # Kernel params
initrd /initrd.img-5.15.0-78-generic # Initramfs image
}
Key kernel parameters here:
root=/dev/sda2: Specifies the root filesystem device.ro: Mounts the root filesystem as read-only initially (remounted as read-write later).quiet splash: Hides kernel messages and shows a splash screen (common in desktop distros).
3. Kernel Initialization & Initramfs
With the kernel and initramfs loaded into RAM, the firmware hands control to the Linux kernel.
Step 1: Kernel Decompression
The kernel image (vmlinuz-*) is compressed (usually with gzip or xz). The kernel first decompresses itself into memory.
Step 2: Hardware Initialization
The kernel initializes core hardware:
- CPU (enabling features like SMP for multi-core systems).
- Memory (detecting RAM size, setting up virtual memory via the MMU).
- Drivers for storage controllers (e.g., SATA, NVMe), USB, and other peripherals (via built-in or module-based drivers).
Step 3: Initramfs (Initial RAM Filesystem)
Most modern Linux systems use an initramfs (initial RAM filesystem) to handle early boot tasks. The initramfs is a temporary, in-memory filesystem (tmpfs) containing:
- Drivers needed to mount the real root filesystem (e.g., if the root is on an encrypted LVM volume or a RAID array).
- Tools like
udev(device manager) andmountto prepare the system.
The kernel executes the initramfs’s /init script, which:
- Scans for storage devices (via
udev). - Loads necessary drivers (e.g., for LUKS encryption or LVM).
- Mounts the real root filesystem (specified by the
root=kernel parameter) to/sysroot. - Switches the root filesystem from the initramfs to
/sysroot(viapivot_rootorswitch_root).
Once the real root is mounted, the initramfs is unmounted, and the kernel runs the init process from the real root: /sbin/init. On systemd-based systems, /sbin/init is a symlink to systemd (lrwxrwxrwx 1 root root 22 Jun 1 12:00 /sbin/init -> /lib/systemd/systemd).
4. systemd Takes Over: The “Init” Phase
At this point, the kernel has done its job, and systemd (the init system) becomes the “parent of all processes” (PID 1). Its primary goal is to start all services and reach the default target (e.g., a graphical desktop or command-line login).
systemd uses units (configuration files) to manage resources. Units include services (.service), mount points (.mount), sockets (.socket), and targets (.target). Targets are groups of units that define system states (e.g., multi-user.target for a non-graphical login).
5. Key systemd Stages: Units, Targets, and Dependencies
systemd processes units in a dependency order, starting with default.target (the system’s desired state). Let’s break down the critical stages:
5.1 Mounting the Root Filesystem
systemd first ensures the root filesystem is mounted read-write (since it was mounted read-only earlier). It uses:
local-fs.target: A target that ensures all local filesystems (from/etc/fstabor systemd mount units) are mounted.systemd-fstab-generator: Converts/etc/fstabentries into transient mount units (e.g.,/run/systemd/generator/boot.mountfor/boot).
Example fstab entry:
UUID=abc123... / ext4 defaults 0 1 # Root filesystem (UUID is preferred over /dev/sda2)
UUID=def456... /boot ext4 defaults 0 2 # /boot partition
5.2 Starting Critical Services
systemd starts services in parallel (where possible) to speed up boot time. Critical early services include:
systemd-journald.service: The system logging daemon (stores logs in/run/log/journalinitially).systemd-udevd.service: Manages device nodes (creates/dev/sda,/dev/nvme0n1, etc.).systemd-networkd.serviceorNetworkManager.service: Configures networking (depending on the distro).systemd-resolved.service: Handles DNS resolution.
Services are started based on dependencies defined in their .service files (e.g., After=network.target ensures a service starts after networking is up).
5.3 Reaching the Default Target
The final stage of systemd’s boot process is reaching the default target, set via /etc/systemd/system/default.target (a symlink to the actual target, e.g., graphical.target).
Common targets:
emergency.target: Minimal shell for emergency repair (no networking, only root mounted).rescue.target: Basic multi-user mode with networking (for troubleshooting).multi-user.target: Full multi-user mode (text login, no GUI).graphical.target: Multi-user mode + GUI (e.g., GNOME, KDE).
To check the default target:
systemctl get-default # Output: graphical.target (or multi-user.target)
Targets depend on other units. For example, graphical.target requires:
multi-user.target(all non-GUI services).display-manager.service(e.g., GDM for GNOME, SDDM for KDE).
6. Post-Boot: User Session & Beyond
Once the default target is reached, the system is ready for user interaction:
Display Manager (GUI Systems)
If graphical.target is active, the display manager (e.g., GDM, LightDM) starts, showing the login screen. After authentication, it launches the user’s desktop environment (GNOME, Xfce, etc.).
Text Login (Non-GUI Systems)
For multi-user.target, the system starts [email protected], which runs login on the first virtual console (tty1), prompting for a username and password.
Ongoing systemd Management
systemd continues to manage services post-boot:
- Socket activation: Services like
sshdornginxstart only when their socket receives traffic (saves resources). - Timer units: Schedule tasks (e.g.,
apt-daily.timerfor daily package updates). - D-Bus integration: Services communicate via D-Bus for dynamic configuration (e.g., NetworkManager notifying apps of network changes).
7. Troubleshooting the Boot Process
If the boot fails, systemd provides tools to diagnose issues:
1. Check the Journal
The journalctl command accesses system logs, including boot messages:
journalctl -b # Logs from the current boot (-b -1 for previous boot)
journalctl -u systemd-fsck.service # Check filesystem check logs
2. Identify Failed Units
List units that failed to start:
systemctl --failed # Output: UNIT LOAD ACTIVE SUB DESCRIPTION
# ● NetworkManager.service loaded failed failed Network Manager
3. Boot into Rescue/Emergency Mode
- Rescue mode (
rescue.target): Starts critical services but stops short of the default target. Access via GRUB: edit the kernel line, addsystemd.unit=rescue.target, and boot. - Emergency mode (
emergency.target): Minimal shell with only the root filesystem mounted (read-only). Addsystemd.unit=emergency.targetto the kernel line.
8. Conclusion
The systemd boot process is a sophisticated sequence of hardware initialization, kernel loading, and service management. From BIOS/UEFI to the final user session, each stage relies on coordination between firmware, kernel, initramfs, and systemd’s unit-based architecture.
Understanding this flow empowers you to troubleshoot boot failures, optimize startup times (e.g., disabling unused services with systemctl disable), and customize your system (e.g., changing the default target). With systemd’s tools like journalctl and systemctl, even complex boot issues become manageable.