GRUB · Kernel · initramfs · systemd · Runlevels — what really happens between power button and shell prompt.
Every Linux startup follows this exact chain. Understanding it lets you diagnose boot failures and configure startup behavior.
BIOS / UEFI ← Power-on self test (POST), finds bootable device
→ MBR / GPT ← First 512 bytes of disk, loads GRUB Stage 1
→ GRUB Stage 2 ← Reads /boot/grub/grub.cfg, shows boot menu
→ initramfs ← Tiny RAM-based filesystem with drivers
→ Kernel ← Decompresses, initializes hardware, mounts /
→ systemd ← PID 1 — starts all services in parallel
→ Login ← getty / display manager → shell
Uses MBR (Master Boot Record) — first 512 bytes of disk. Max 4 primary partitions. Max 2TB disk. No Secure Boot.
Uses GPT partition table. Supports disks over 2TB. Secure Boot support. Stores config in NVRAM. Faster POST.
$ ls /sys/firmware/efi && echo "UEFI" || echo "Legacy BIOS" $ cat /sys/firmware/efi/fw_platform_size # 64 = 64-bit UEFI
GRUB2 (Grand Unified Bootloader 2) is the standard bootloader on nearly all Linux distros. It presents the boot menu and hands control to the kernel.
/etc/default/grub # Main config — edit this one /boot/grub/grub.cfg # Auto-generated — DO NOT edit directly /etc/grub.d/ # Scripts that build grub.cfg
$ sudo nano /etc/default/grub # Common settings to change: GRUB_TIMEOUT=5 # seconds to show menu GRUB_CMDLINE_LINUX_DEFAULT="quiet splash" # kernel boot params $ sudo update-grub # Debian/Ubuntu $ sudo grub2-mkconfig -o /boot/grub2/grub.cfg # RHEL/Fedora $ sudo sshd -t # always test before rebooting
$ sudo grub-install /dev/sda # install to disk $ sudo grub-install --target=x86_64-efi --efi-directory=/boot/efi # UEFI
/boot/vmlinuz-* # Compressed kernel image /boot/initrd.img-* # Initial RAM disk /boot/config-* # Build config for this kernel /lib/modules/$(uname -r)/ # Loadable kernel modules /proc/cmdline # Kernel boot parameters used this boot
$ uname -r # current kernel version $ uname -a # full info: kernel, hostname, arch $ cat /proc/version # kernel version + compiler used $ cat /proc/cmdline # boot parameters passed to kernel $ lsmod # list all loaded kernel modules $ modinfo <module> # info about a specific module $ sudo modprobe <module> # load a module $ sudo rmmod <module> # remove a module # List installed kernels: $ dpkg --list | grep linux-image # Debian/Ubuntu $ rpm -qa | grep -i kernel # RHEL/Fedora
After the kernel loads, it starts PID 1 — either legacy init or modern systemd. SysV init used numbered runlevels; systemd uses named targets.
Runlevel 0 → poweroff.target # Shutdown Runlevel 1 → rescue.target # Single user / maintenance Runlevel 3 → multi-user.target # CLI + networking (servers) Runlevel 5 → graphical.target # GUI + networking (desktop) Runlevel 6 → reboot.target # Reboot
$ systemctl get-default # current default target $ sudo systemctl set-default multi-user.target # boot to CLI $ sudo systemctl set-default graphical.target # boot to GUI $ sudo systemctl isolate rescue.target # switch now (no reboot) # Boot troubleshooting: $ journalctl -b # logs from this boot $ journalctl -b -1 # logs from previous boot $ systemd-analyze # total boot time $ systemd-analyze blame # which services slowed boot $ systemd-analyze critical-chain # critical path to default target
$ chkconfig --list # list all services and runlevel status $ chkconfig nginx on # enable at boot (runlevels 3,4,5) $ ntsysv # text-based UI for services
Spin up a Linux droplet in 60 seconds. Practice everything in these tutorials on a real server.
Get Started →