Linux Boot Process
BIOS/UEFI to Userspace
graph TD
classDef fw fill:#2c3e50,stroke:#1a252f,color:#fff
classDef boot fill:#e67e22,stroke:#d35400,color:#fff
classDef kern fill:#e74c3c,stroke:#c0392b,color:#fff
classDef init fill:#9b59b6,stroke:#8e44ad,color:#fff
classDef svc fill:#2ecc71,stroke:#27ae60,color:#fff
POWER["Power ON"]:::fw
subgraph Firmware["Firmware (BIOS or UEFI)"]
POST["POST: Power-On Self Test check RAM, CPU, devices"]:::fw
BIOS["BIOS: reads MBR (first 512 bytes of disk) hands off to bootloader"]:::fw
UEFI["UEFI: reads EFI System Partition directly loads bootloader faster, Secure Boot support"]:::fw
end
GRUB["GRUB2 Bootloader /boot/grub2/grub.cfg shows OS selection menu loads kernel + initramfs into RAM"]:::boot
KERNEL["Linux Kernel decompresses itself initializes CPU, memory, devices mounts initramfs as temporary root /"]:::kern
INITRAMFS["initramfs (initial RAM filesystem) minimal filesystem in RAM contains drivers needed to mount real root (disk drivers, LVM, LUKS decrypt)"]:::kern
REALROOT["Mount real root filesystem (ext4/xfs on /dev/sda1 or LVM volume) switch_root to real /"]:::kern
INIT["PID 1: systemd (or SysVinit/OpenRC) first userspace process starts all services"]:::init
TARGETS["systemd targets multi-user.target graphical.target"]:::init
SERVICES["Services start in parallel sshd, networkd, nginx, docker, etc."]:::svc
LOGIN["Login prompt / getty"]:::svc
POWER --> Firmware
Firmware --> GRUB
GRUB --> KERNEL
KERNEL --> INITRAMFS
INITRAMFS --> REALROOT
REALROOT --> INIT
INIT --> TARGETS
TARGETS --> SERVICES
SERVICES --> LOGIN
BIOS vs UEFI:
| BIOS | UEFI | |
|---|---|---|
| Partition table | MBR (max 2TB disk, 4 partitions) | GPT (max 9.4ZB, 128 partitions) |
| Boot code location | First 512 bytes of disk (MBR) | EFI System Partition (FAT32, /boot/efi) |
| Secure Boot | No | Yes (verifies bootloader signature) |
| Speed | Slower | Faster (parallel init) |
| Common on | Pre-2012 hardware | All modern hardware |
initramfs and Why It Exists
The kernel can't mount the real root filesystem directly because it might need drivers that aren't compiled in (e.g., LUKS encryption, LVM, NFS root, specific disk drivers). initramfs is a temporary filesystem that provides those drivers.
graph LR
classDef kern fill:#e74c3c,stroke:#c0392b,color:#fff
classDef init fill:#9b59b6,stroke:#8e44ad,color:#fff
classDef real fill:#2ecc71,stroke:#27ae60,color:#fff
KERNEL["Kernel loaded into RAM no disk drivers yet"]:::kern
INITRD["initramfs mounted as / has: busybox, dracut scripts disk drivers as kernel modules cryptsetup for LUKS"]:::init
DRIVERS["Load disk drivers decrypt LUKS volume assemble LVM/RAID"]:::init
REAL["Mount real / (ext4/xfs) switch_root initramfs discarded from RAM"]:::real
KERNEL --> INITRD --> DRIVERS --> REAL
# Inspect initramfs contents
lsinitrd /boot/initramfs-$(uname -r).img
# Rebuild after driver changes
dracut --force # RHEL/CentOS
update-initramfs -u # Debian/Ubuntu
systemd
systemd is PID 1 — the init system that starts and manages all services. It replaced SysVinit for parallel service startup and better dependency management.
graph TD
classDef target fill:#9b59b6,stroke:#8e44ad,color:#fff
classDef svc fill:#2ecc71,stroke:#27ae60,color:#fff
classDef dep fill:#3498db,stroke:#2980b9,color:#fff
DEFAULT["default.target (usually multi-user or graphical)"]:::target
DEFAULT --> MULTI["multi-user.target all non-GUI services"]:::target
MULTI --> BASIC["basic.target timers, paths, sockets"]:::target
BASIC --> SYSINIT["sysinit.target mount filesystems, swap, hostname"]:::target
MULTI --> SSHD["sshd.service"]:::svc
MULTI --> NGINX["nginx.service"]:::svc
MULTI --> DOCKER["docker.service"]:::svc
MULTI --> NETWORK["network-online.target"]:::dep
NETWORK --> APP["myapp.service After=network-online.target"]:::svc
Unit File Anatomy
# /etc/systemd/system/myapp.service
[Unit]
Description=My Go Application
After=network-online.target postgresql.service # start after these
Requires=postgresql.service # hard dependency (fail if postgres fails)
Wants=redis.service # soft dependency (start redis if possible)
[Service]
Type=simple # exec: ExecStart is the main process
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID # reload config on: systemctl reload myapp
WorkingDirectory=/opt/myapp
User=appuser
Group=appuser
Restart=on-failure # restart if exits non-zero
RestartSec=5s # wait 5s before restart
StartLimitBurst=5 # max 5 restarts
StartLimitIntervalSec=30s # within 30s window — then fail permanently
# Resource limits
LimitNOFILE=65536 # max open file descriptors
MemoryMax=512M # cgroup memory limit
CPUQuota=200% # max 2 CPU cores
# Security hardening
NoNewPrivileges=true # process cannot gain extra privileges
PrivateTmp=true # own /tmp (not shared with other services)
ProtectSystem=strict # /usr, /boot, /etc read-only
ReadWritePaths=/var/lib/myapp # only this path is writable
# Environment
Environment=APP_ENV=production
EnvironmentFile=/etc/myapp/env # load from file
[Install]
WantedBy=multi-user.target # enable for this target
Essential systemctl Commands
systemctl start myapp
systemctl stop myapp
systemctl restart myapp
systemctl reload myapp # reload config (sends ExecReload signal)
systemctl status myapp # detailed status + last log lines
systemctl enable myapp # auto-start on boot
systemctl disable myapp
systemctl daemon-reload # reload unit files after editing
systemctl list-units --failed # see broken services
systemctl list-dependencies myapp # show dependency tree
# Logs
journalctl -u myapp -f # follow logs
journalctl -u myapp --since "1 hour ago"
journalctl -u myapp -n 100 # last 100 lines
journalctl -p err -b # errors since last boot
journalctl --disk-usage # how much journal space used
# Boot analysis
systemd-analyze # total boot time
systemd-analyze blame # which units took longest
systemd-analyze critical-chain # critical path of boot
Service Types
| Type | Meaning | Use for |
|---|---|---|
simple |
ExecStart process IS the service | Most daemons |
forking |
ExecStart forks, parent exits | Old-style daemons (nginx, apache) |
notify |
Process sends sd_notify(READY=1) when ready |
Services that take time to init |
oneshot |
Process runs and exits (not a daemon) | Init scripts, migrations |
idle |
Like simple but waits until boot is done | Low-priority startup tasks |