Skip to content

Boot Process: BIOS → GRUB → Kernel → systemd

Chapter 2: Boot Process: BIOS → GRUB → Kernel → systemd

Section titled “Chapter 2: Boot Process: BIOS → GRUB → Kernel → systemd”

By the end of this chapter, you will:

  • Understand every stage of the Linux boot process in precise detail
  • Know how to diagnose boot failures at each stage
  • Understand how to customize the bootloader and kernel parameters
  • Know how systemd target units map to traditional runlevels
  • Be able to create production systemd services correctly

The boot process is the sequence of events that happens from the moment you press the power button until you get a login prompt. It’s like waking up: first your brain turns on (BIOS/UEFI), then you load your core memories (Kernel), and finally you start your daily routines (systemd and services).

┌─────────────────────────────────────────────────────────────────┐
│ POWER ON │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────────┐
│ STAGE 1: FIRMWARE │
│ BIOS or UEFI │
│ │
│ • CPU starts at fixed address (0xFFFFFFF0 for x86) │
│ • POST (Power-On Self Test): tests RAM, CPU, devices │
│ • Finds boot device (NVMe, SATA, USB, network) │
│ • BIOS: loads first 512 bytes (MBR) from boot device │
│ • UEFI: reads EFI System Partition (ESP), runs .efi file │
│ │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────────┐
│ STAGE 2: BOOTLOADER │
│ GRUB2 (most Linux systems) │
│ │
│ • GRUB loaded by BIOS/UEFI │
│ • Reads /boot/grub/grub.cfg │
│ • Shows boot menu (if configured) │
│ • Loads kernel (vmlinuz) into RAM │
│ • Loads initramfs/initrd into RAM │
│ • Passes kernel command line parameters │
│ • Hands control to kernel │
│ │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────────┐
│ STAGE 3: KERNEL INITIALIZATION │
│ │
│ • Kernel decompresses itself │
│ • Sets up CPU, memory, early hardware │
│ • Mounts initramfs as temporary root filesystem │
│ • Loads essential modules (disk drivers, filesystem drivers) │
│ • Mounts real root filesystem │
│ • Executes /sbin/init (PID 1) — now systemd in modern Linux │
│ │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────────┐
│ STAGE 4: SYSTEMD (PID 1) │
│ │
│ • Reads /etc/systemd/system/ and /lib/systemd/system/ │
│ • Activates default.target (usually multi-user.target) │
│ • Starts units in dependency order (parallel where possible) │
│ • Launches all configured services, sockets, timers │
│ • System is now operational │
│ │
└──────────────────────────┬──────────────────────────────────────┘
┌──────────────────────────▼──────────────────────────────────────┐
│ SYSTEM OPERATIONAL │
│ Login prompts, services running, applications available │
└─────────────────────────────────────────────────────────────────┘

BIOS (Basic Input/Output System) is the legacy firmware from the 1970s–2000s.

BIOS Boot Sequence
──────────────────
1. CPU starts at address 0xFFFFFFF0 (Reset Vector)
2. BIOS code runs from ROM
3. POST: counts RAM, tests hardware
4. Reads boot device order from CMOS settings
5. Reads first 446 bytes of MBR (Master Boot Record)
6. The 446-byte MBR code is GRUB Stage 1
7. GRUB Stage 1 loads GRUB Stage 2 from disk
8. GRUB Stage 2 reads grub.cfg, shows menu, loads kernel
MBR Layout (512 bytes):
┌─────────────────────────────────────────────────┐
│ Bootstrap Code (446 bytes) │ Partition Table │ Magic │
│ GRUB Stage 1 │ (64 bytes, 4 x │ 0xAA55│
│ │ 16-byte entries)│ │
└─────────────────────────────────────────────────┘
0 446 510 512

UEFI (Unified Extensible Firmware Interface) replaced BIOS for most modern hardware.

UEFI Boot Sequence
──────────────────
1. Firmware runs from UEFI ROM
2. POST and hardware initialization
3. UEFI reads NVRAM for boot entries
4. Finds EFI System Partition (ESP) — fat32 formatted
5. Loads /EFI/ubuntu/grubx64.efi (or similar)
6. GRUB EFI binary takes over
UEFI Advantages:
✓ Supports disks >2TB (GPT partition table)
✓ Secure Boot (cryptographic verification of bootloader)
✓ Faster boot (no need for MBR stage 1/2)
✓ Network boot (PXE) built-in
✓ 64-bit mode from the start
✓ Driver model (network, disk access in firmware)
ESP Layout:
/boot/efi/
├── EFI/
│ ├── ubuntu/
│ │ ├── grubx64.efi # GRUB EFI binary
│ │ └── shimx64.efi # Secure Boot shim
│ ├── BOOT/
│ │ └── BOOTX64.EFI # Fallback bootloader
│ └── Microsoft/ # Windows bootloader (if dual boot)
└── ...
Terminal window
# Check if system uses UEFI or BIOS
[ -d /sys/firmware/efi ] && echo "UEFI" || echo "BIOS"
# View UEFI boot entries
efibootmgr -v
# View EFI System Partition contents
ls /boot/efi/EFI/
# Check Secure Boot status
mokutil --sb-state

GRUB (GRand Unified Bootloader) is what most Linux systems use. GRUB2 is the current version.

Terminal window
# Main GRUB config (auto-generated, DO NOT edit directly)
cat /boot/grub/grub.cfg
# User-editable GRUB defaults
cat /etc/default/grub
# Directory for custom GRUB scripts
ls /etc/grub.d/
# After editing /etc/default/grub, regenerate:
sudo update-grub # Debian/Ubuntu
sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/CentOS
# Useful /etc/default/grub settings:
GRUB_TIMEOUT=5 # Seconds to show menu
GRUB_DEFAULT=0 # Default menu entry (0=first)
GRUB_CMDLINE_LINUX="quiet splash" # Kernel parameters for all entries
GRUB_CMDLINE_LINUX_DEFAULT="" # Params for default entry only

Critical Kernel Parameters (Passed by GRUB)

Section titled “Critical Kernel Parameters (Passed by GRUB)”

These parameters fundamentally change kernel behavior:

Terminal window
# View current kernel parameters (what was used at boot)
cat /proc/cmdline
# Example output:
# BOOT_IMAGE=/vmlinuz-6.8.0-45-generic root=UUID=abc123 ro quiet splash
# Common kernel parameters:
# root= — Root device (can be UUID, /dev/sda1, LABEL=)
# ro — Mount root read-only initially
# quiet — Suppress non-critical kernel messages
# splash — Show graphical splash screen
# init= — Override init process (use init=/bin/bash for recovery)
# single — Boot into single-user mode (runlevel 1)
# mem= — Limit available RAM (testing purposes)
# maxcpus= — Limit CPU count
# nomodeset — Disable GPU kernel module (use for video troubleshooting)
# systemd.unit=— Override systemd target (systemd.unit=rescue.target)
# selinux=0 — Disable SELinux (DANGEROUS, for emergency only)
# apparmor=0 — Disable AppArmor
Terminal window
# /etc/default/grub production settings
GRUB_TIMEOUT=1 # Short timeout (reduce attack window)
GRUB_TIMEOUT_STYLE=menu # Show menu briefly
# Set GRUB password to prevent unauthorized boot modification
# This prevents someone with physical access from booting into single-user mode
grub-mkpasswd-pbkdf2
# Enter password, get PBKDF2 hash
# Add to /etc/grub.d/40_custom:
set superusers="admin"
password_pbkdf2 admin grub.pbkdf2.sha512.10000.<HASH>
# Restrict menu entry to superusers only
# (in grub.cfg, add --unrestricted for entries users can use without password)

After GRUB hands control to the kernel, a complex initialization sequence occurs.

initramfs (initial RAM filesystem) is a temporary root filesystem loaded into RAM before the real root filesystem is mounted.

Why it exists: The kernel needs to mount the real root filesystem, but that might require drivers that aren’t compiled in (e.g., NVMe driver, LVM, LUKS encryption, RAID). initramfs contains these drivers.

The initramfs Problem and Solution
────────────────────────────────────
Problem: Kernel needs to mount /dev/nvme0n1p1, but
the NVMe driver is a loadable module.
Modules live on the root filesystem.
The root filesystem needs the NVMe driver to access.
→ Chicken-and-egg problem!
Solution: initramfs
1. GRUB loads kernel + initramfs into RAM
2. Kernel mounts initramfs as temporary /
3. initramfs contains the NVMe module (built-in)
4. initramfs script loads NVMe module
5. Now kernel can see /dev/nvme0n1p1
6. Real root filesystem mounted
7. initramfs unmounted, real / takes over
8. PID 1 (systemd) starts from real filesystem
Contents of initramfs:
┌────────────────────────────────┐
│ /bin/sh (busybox or dash) │
│ /lib/modules/ (needed mods) │
│ /scripts/ (boot scripts) │
│ /sbin/init → systemd │
│ cryptsetup (for LUKS) │
│ lvm2 tools (for LVM) │
│ mdadm (for software RAID) │
└────────────────────────────────┘
Terminal window
# View initramfs contents
lsinitramfs /boot/initrd.img-$(uname -r)
# Or on RHEL/CentOS
lsinitrd /boot/initramfs-$(uname -r).img
# Rebuild initramfs (needed after adding kernel modules)
update-initramfs -u # Debian/Ubuntu
dracut --force # RHEL/CentOS/Fedora
# Extract initramfs for debugging
mkdir /tmp/initramfs && cd /tmp/initramfs
zcat /boot/initrd.img-$(uname -r) | cpio -idmv
# Or with newer zstd compression:
zstd -d /boot/initrd.img-$(uname -r) -o /tmp/initrd.cpio
cpio -idmv < /tmp/initrd.cpio
Kernel Startup (simplified)
────────────────────────────
1. head.S / head_64.S — Architecture-specific assembly
Sets up page tables, GDT, IDT
2. start_kernel() — First C function in kernel
3. setup_arch() — CPU detection, memory map parsing
4. mm_init() — Memory management initialization
5. sched_init() — Scheduler initialization
6. vfs_caches_init() — VFS and dcache initialization
7. rest_init() — Creates kernel threads
├── kernel_thread(kthreadd) — Parent of all kernel threads
└── kernel_thread(kernel_init) — Will become PID 1
8. kernel_init()
├── do_initcalls() — Calls all __init functions
│ (driver initialization)
├── mount_root() — Mounts initramfs
├── prepare_namespace() — Mounts real root filesystem
└── run_init_process("/sbin/init") — Executes systemd

Once the kernel executes /sbin/init (which is systemd on modern Linux), the user-space boot begins.

systemd is the parent of all user-space processes
─────────────────────────────────────────────────
PID 1: systemd
├── journald (log collection)
├── udevd (device management)
├── networkd (networking)
├── resolved (DNS)
├── logind (login sessions)
├── dbus-daemon (D-Bus message bus)
├── nginx.service (your web server)
├── postgresql.service (your database)
├── sshd.service (SSH daemon)
└── ... (all other services)

Every resource systemd manages is a unit. Units are defined in unit files:

Unit TypeExtensionPurpose
Service.serviceDaemons and processes
Socket.socketSocket-activated services
Timer.timerScheduled jobs (cron replacement)
Target.targetGroups of units (like runlevels)
Mount.mountFilesystem mounts
Device.deviceHardware devices
Path.pathFile/directory monitoring
Slice.sliceResource control groups
Traditional Runlevels → systemd Targets
─────────────────────────────────────────
Runlevel 0 → poweroff.target
Runlevel 1 → rescue.target
Runlevel 2 → multi-user.target
Runlevel 3 → multi-user.target
Runlevel 5 → graphical.target
Runlevel 6 → reboot.target
Target Dependency Chain:
┌──────────────────────────────────────────┐
│ graphical.target │
│ └── multi-user.target │
│ └── basic.target │
│ └── sysinit.target │
│ └── local-fs.target
│ └── network.target
└──────────────────────────────────────────┘
Terminal window
# View current target (runlevel)
systemctl get-default
# Change default target
systemctl set-default multi-user.target
# Switch to a different target (immediately)
systemctl isolate rescue.target
# List all targets
systemctl list-units --type=target
# View which units are in a target
systemctl list-dependencies multi-user.target

A properly written service unit is essential for production reliability. Here’s a complete example:

/etc/systemd/system/myapp.service
[Unit]
Description=My Production Application
Documentation=https://docs.myapp.com
# Hard dependencies (must be active before this starts)
Requires=network-online.target
After=network-online.target postgresql.service
# Soft dependencies (start after if available, but don't fail if not)
Wants=redis.service
After=redis.service
[Service]
Type=notify # App signals systemd when ready (most correct)
# Other types: simple (default), forking, oneshot, dbus, idle
# Run as non-root user
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
# Environment
Environment=NODE_ENV=production
EnvironmentFile=/etc/myapp/env # Load secrets from file
# The actual command
ExecStart=/opt/myapp/bin/server --port 8080
ExecReload=/bin/kill -HUP $MAINPID # Reload without restart
ExecStop=/bin/kill -TERM $MAINPID # Graceful shutdown
# Restart policy
Restart=always # Always restart on failure
RestartSec=5 # Wait 5 seconds before restarting
StartLimitInterval=60 # Time window for start limit
StartLimitBurst=5 # Max 5 restarts in 60 seconds
# Resource limits
LimitNOFILE=65536 # Max open file descriptors
LimitNPROC=4096 # Max processes/threads
MemoryMax=2G # Max RAM (OOM kill if exceeded)
CPUQuota=200% # Max 2 CPU cores
# Security hardening
NoNewPrivileges=yes # Cannot gain new privileges
PrivateTmp=yes # Isolated /tmp
ProtectSystem=strict # Read-only /usr, /boot, /etc
ProtectHome=yes # No access to /home
ReadWritePaths=/var/lib/myapp # Allow write to specific dir
CapabilityBoundingSet= # Drop all capabilities
AmbientCapabilities= # No ambient capabilities
# Timeouts
TimeoutStartSec=30 # Fail if not ready within 30s
TimeoutStopSec=30 # Force kill after 30s
[Install]
WantedBy=multi-user.target
Terminal window
# Deploy the service
sudo systemctl daemon-reload # Reload unit files
sudo systemctl enable myapp # Enable on boot
sudo systemctl start myapp # Start now
sudo systemctl status myapp # Check status
journalctl -u myapp -f # Follow logs

Terminal window
# Measure boot time breakdown
systemd-analyze # Total boot time
systemd-analyze blame # Which units took longest
systemd-analyze critical-chain # Critical path of boot
systemd-analyze plot > boot.svg # SVG visualization
# Example output of systemd-analyze blame:
# 23.543s NetworkManager-wait-online.service
# 8.281s snapd.service
# 4.371s dev-sda1.device
# 3.246s fwupd.service
# 2.841s accounts-daemon.service
# Example: Reduce boot time by masking slow units
# NetworkManager-wait-online delays boot by waiting for network
# On servers, use networkd's systemd-networkd-wait-online instead
sudo systemctl mask NetworkManager-wait-online.service

Scenario 1: System Won’t Boot — Emergency Shell

Section titled “Scenario 1: System Won’t Boot — Emergency Shell”
GRUB menu → Edit boot entry → Add to kernel line:
systemd.unit=emergency.target
or
init=/bin/bash
Terminal window
# In emergency shell:
# Mount root filesystem read-write
mount -o remount,rw /
# Check filesystem errors
fsck /dev/sda1
# View systemd journal from previous failed boot
journalctl -b -1 --priority=3 # Errors from last boot
# Check what failed
systemctl --failed
systemctl status <failed-unit>
Terminal window
# Check service status
systemctl status nginx.service
# View full logs for the service
journalctl -u nginx.service --no-pager -n 100
# View kernel messages around service start
journalctl -k -b | grep -A 5 "nginx"
# Check if a dependency failed
systemctl list-dependencies nginx.service
systemd-analyze critical-chain nginx.service
# Debug service startup interactively
# (starts with output to terminal)
systemd-run --unit=test-nginx -t /usr/sbin/nginx -g "daemon off;"

Scenario 3: Slow Boot Diagnosed in Production

Section titled “Scenario 3: Slow Boot Diagnosed in Production”
Terminal window
# The culprit: NetworkManager-wait-online.service waiting 90s
systemd-analyze blame | head -5
# 90.000s NetworkManager-wait-online.service
# Fix for servers that don't need GUI networking:
# Option 1: Mask the wait service
sudo systemctl mask NetworkManager-wait-online.service
# Option 2: Configure network properly with networkd
sudo systemctl enable --now systemd-networkd
sudo systemctl enable systemd-networkd-wait-online
# Verify fix
systemd-analyze
# Before: Startup finished in 103.342s
# After: Startup finished in 8.234s

Scenario: Recovering a Server with Corrupted GRUB

Section titled “Scenario: Recovering a Server with Corrupted GRUB”
Terminal window
# Boot from live ISO or rescue image
# Step 1: Mount the broken system's partitions
mount /dev/sda2 /mnt # Root partition
mount /dev/sda1 /mnt/boot # Boot partition
mount --bind /dev /mnt/dev
mount --bind /proc /mnt/proc
mount --bind /sys /mnt/sys
# Step 2: chroot into broken system
chroot /mnt /bin/bash
# Step 3: Reinstall GRUB
grub-install /dev/sda # BIOS
# or for UEFI:
mount /dev/sda1 /boot/efi
grub-install --target=x86_64-efi --efi-directory=/boot/efi
# Step 4: Regenerate GRUB config
update-grub # Ubuntu/Debian
grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/CentOS
# Step 5: Exit and reboot
exit
umount -R /mnt
reboot

Scenario: Production System with Slow initramfs

Section titled “Scenario: Production System with Slow initramfs”

An on-call engineer reports that a fleet of servers takes 3+ minutes to boot after a kernel update. Investigation:

Terminal window
# Boot with early debug output
# Add to kernel parameters: rd.debug rd.log
# In GRUB: press 'e' and add to kernel line
# Check initramfs boot log
journalctl -b | grep "dracut\|initramfs" | head -40
# The problem: RAID assembly timeout
# udev waited 30s for each of 6 RAID members
# Fix: Add rdblacklist=megaraid_sas to GRUB params
# and set GRUB_CMDLINE_LINUX="rd.timeout=60"
# Or specify the root device explicitly to skip discovery
# GRUB_CMDLINE_LINUX="root=UUID=abc123-def456 rd.timeout=30"

PracticeWhyImplementation
Set short GRUB timeoutFaster boot, less attack windowGRUB_TIMEOUT=1
Password-protect GRUBPrevent single-user mode bypassgrub-mkpasswd-pbkdf2
Use Type=notify for servicesAccurate dependency trackingsystemd knows when service is truly ready
Set resource limits in servicePrevent runaway processesMemoryMax=, CPUQuota=
Enable WatchdogAuto-restart hung servicesWatchdogSec=30 in [Service]
Use PrivateTmp=yesIsolate /tmp per serviceSecurity hardening
Set Restart=alwaysAuto-recovery from crashesNever lose a service silently

Q1: Explain the entire Linux boot process from power-on to login prompt.

Answer: (1) Firmware (BIOS/UEFI): CPU starts at reset vector, runs POST, selects boot device. BIOS loads MBR (512 bytes); UEFI reads the EFI System Partition and loads a .efi binary. (2) GRUB2: Reads grub.cfg, shows boot menu, loads kernel (vmlinuz) and initramfs into RAM, passes kernel parameters, hands over execution. (3) Kernel initialization: Decompresses itself, initializes CPU/memory/drivers, mounts initramfs as temporary root, loads any needed modules (LUKS, LVM, NVMe), mounts real root filesystem, executes /sbin/init (PID 1). (4) systemd: Reads unit files, resolves dependencies, starts units in parallel up to default.target, brings up all services. Login prompt appears when getty@tty1.service or sshd.service is ready.

Q2: What is initramfs and why is it needed?

Answer: initramfs (initial RAM filesystem) is a small compressed filesystem packed alongside the kernel by the bootloader. It’s needed to solve a chicken-and-egg problem: the kernel needs drivers (e.g., for NVMe, LVM, or LUKS encryption) to mount the real root filesystem, but those drivers are stored as loadable modules on the root filesystem. initramfs contains a minimal set of tools and modules. The kernel mounts it first, runs its startup scripts to load required drivers and potentially unlock encrypted drives, then mounts the real root filesystem and switches over to it.

Q3: What is the difference between Requires= and Wants= in a systemd unit file?

Answer: Requires= is a hard dependency — if the required unit fails to start, this unit will also fail. Wants= is a soft dependency — if the wanted unit fails, this unit continues starting anyway. In production, use Wants= for optional dependencies (like a cache) and Requires= for mandatory ones (like a database). Always pair with After= to control ordering, because Requires=/Wants= only control activation, not ordering.

Q4: How would you debug a service that fails to start with systemctl status showing “Failed to start”?

Answer: (1) systemctl status <service> — often shows the last error message. (2) journalctl -u <service> -n 50 --no-pager — full service logs. (3) systemctl list-dependencies <service> — check if a dependency failed. (4) systemd-analyze critical-chain <service> — dependency chain. (5) Try running the ExecStart= command manually as the service user to see the exact error. (6) Check EnvironmentFile exists and has correct syntax. (7) Check directory/file permissions. (8) Check User= and Group= settings.


Terminal window
# 1. Check total boot time
systemd-analyze
# 2. Find the 10 slowest units
systemd-analyze blame | head -10
# 3. Visualize the boot critical path
systemd-analyze critical-chain
# 4. Generate SVG (optional, if you have a browser)
systemd-analyze plot > /tmp/boot-plot.svg
Terminal window
# Create a simple test service
sudo tee /etc/systemd/system/mytest.service << 'EOF'
[Unit]
Description=My Test Service
After=network.target
[Service]
Type=simple
User=nobody
ExecStart=/bin/sleep infinity
Restart=always
RestartSec=5
PrivateTmp=yes
NoNewPrivileges=yes
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl start mytest
sudo systemctl status mytest
journalctl -u mytest
# Test restart behavior
sudo systemctl kill --signal=SIGKILL mytest
# Wait 5 seconds, then check:
sudo systemctl status mytest # Should show restarted
# Clean up
sudo systemctl stop mytest
sudo systemctl disable mytest
sudo rm /etc/systemd/system/mytest.service
sudo systemctl daemon-reload
Terminal window
# On a VM (do NOT do this on production):
# 1. Reboot and interrupt GRUB
# 2. Press 'e' to edit the boot entry
# 3. Find the linux line
# 4. Append: systemd.unit=rescue.target
# 5. Press Ctrl+X to boot
# 6. You now have a rescue shell
# 7. Change root password, fix files, etc.
# 8. Reboot normally

StageKey ComponentsFailure Point
FirmwareBIOS/UEFI, POSTDead hardware, wrong boot order
BootloaderGRUB2, grub.cfgCorrupted GRUB, wrong kernel path
Kernel initvmlinuz, initramfsMissing modules, wrong root device
systemdUnit files, targetsFailed service, dependency issue

Chapter 1 (Linux Architecture); know what a kernel is and what BIOS/UEFI does.


Advantages: Highly configurable (GRUB), systemd allows parallel service startup (fast boot). Disadvantages: Complex to troubleshoot (many stages), breaking GRUB can leave the system unbootable.


  • Editing /boot/grub2/grub.cfg directly — it’s auto-generated; always edit /etc/default/grub then run grub2-mkconfig.
  • Assuming BIOS and UEFI are interchangeable — UEFI supports Secure Boot, GPT disks, and faster boot; BIOS is MBR-only legacy.
  • Forgetting to rebuild initramfs after adding a kernel module — the driver won’t be available at boot time.
  • Not knowing systemd targets map to runlevels: multi-user.target≈runlevel 3, graphical.target≈runlevel 5.
  • Believing dmesg shows all boot messages — use journalctl -b for the complete boot log including systemd units.

SymptomCauseDiagnosisFix
GRUB rescue prompt on bootGRUB can’t find stage2 or configAt prompt: lsto list partitions;set root=(hd0,1)theninsmod normal; normal“Reinstall GRUB: grub2-install /dev/sda && grub2-mkconfig -o /boot/grub2/grub.cfg
Kernel panic: VFS cannot mount rootWrong root= parameter or missing driver in initramfsBoot rescue ISO; blkidto verify UUIDs;cat /etc/fstab“Rebuild initramfs: dracut --force; fix GRUB root= to match blkid UUID
Boot to emergency modeFailed mount in /etc/fstab or corrupted filesystemRead: journalctl -xb; check which unit failed: systemctl list-units —failed“Fix /etc/fstab entry; add nofail option; run fsck on suspect filesystem
Extremely slow boot (>60s)Timeout waiting for network or slow service start“systemd-analyze blamehead -20; systemd-analyze plot > boot.svg“

Objective: Trace the complete boot sequence on your system.

Terminal window
# 1. Measure boot time breakdown
systemd-analyze time
systemd-analyze blame | head -15
# 2. Generate visual boot timeline
systemd-analyze plot > /tmp/boot.svg
# Open boot.svg in a browser
# 3. View GRUB menu entries
grep -A5 "menuentry" /boot/grub2/grub.cfg | head -30
# 4. Check current GRUB defaults
cat /etc/default/grub
# 5. Inspect initramfs contents
lsinitrd /boot/initramfs-$(uname -r).img | grep -E "\.ko$" | head -20
# 6. View systemd default target
systemctl get-default
systemctl list-units --type=target --state=active
# 7. Read complete boot journal
journalctl -b | head -80

  1. Run systemd-analyze blame. Find the slowest unit and research whether it can be safely disabled.
  2. Modify /etc/default/grub to add quiet to kernel parameters; regenerate GRUB config; verify the change takes effect.
  3. Examine your initramfs: which filesystem drivers does it include? Why does it need them before the root filesystem is mounted?
  4. Use systemctl list-dependencies graphical.target to draw the dependency graph for reaching the graphical target.
  5. Write a systemd service unit file for a simple bash script that logs the boot time to /var/log/myboot.log.

  • Boot sequence: BIOS/UEFI → POST → GRUB stage 1 (MBR) → GRUB stage 2 → kernel + initramfs → real rootfs → PID 1 (systemd).
  • initramfs is a temporary RAM-based root filesystem containing drivers needed to mount the real root partition.
  • GRUB reads grub.cfg; generated from /etc/default/grub by grub2-mkconfig; never edit grub.cfg directly.
  • systemd starts services in parallel using a dependency graph; systemd-analyze measures the result.
  • journalctl -b = current boot logs; -b -1 = previous boot logs — essential for debugging boot failures.
  • Kernel parameters (in GRUB linux line): root=, ro/rw, quiet, crashkernel= — all control early boot behavior.


  • Chapter 1 — Kernel architecture and execution context
  • Chapter 7 — systemd deep dive and unit files
  • Chapter 46 — kexec: fast kernel reboots

Last Updated: July 2026