Booting, init systems and services

Firmware and bootloaders, how the kernel starts the first process, systemd units versus init scripts, targets and dependencies, and where to find service logs.

The boot sequence

  1. Firmware (UEFI or BIOS) initialises hardware and finds a bootable device or loader.
  2. The bootloader loads the kernel and an initial ramdisk into memory and hands over control.
  3. The kernel initialises devices, mounts the root file system and starts the first process, PID 1.
  4. PID 1 brings up services according to its configuration and reaches the default target.
  5. Login prompts, display managers and user services start.
  6. On shutdown, PID 1 stops services in reverse dependency order.
systemd-analyze                     # total boot time and the biggest stages
systemd-analyze blame | head -15    # slowest units
systemd-analyze critical-chain      # the path that determined the boot time

journalctl -b                       # this boot's log
journalctl -b -1                    # previous boot, useful after a failed one
journalctl -b --list-boots          # available boots

systemd units and where they differ from init scripts

# /etc/systemd/system/api.service
[Unit]
Description=API server
After=network-online.target
Wants=network-online.target

[Service]
Type=exec
User=app
WorkingDirectory=/srv/api
ExecStart=/srv/api/bin/server --config /etc/api.toml
Restart=on-failure
RestartSec=2
LimitNOFILE=65536
Environment=LOG_LEVEL=info

# apply resource limits rather than a shell wrapper
MemoryMax=512M
CPUQuota=150%

[Install]
WantedBy=multi-user.target
Aspectinit scriptssystemd
DependenciesOrder by a numeric prefixDeclared with After and Requires
Parallel startRarelyYes, by default
Restart on failureShell logic you writeRestart=on-failure
Resource limitsWrapped in ulimit callsDirectives in the unit
LoggingRedirect to a file yourselfCaptured in the journal
Socket activationNot availableSupported per socket unit
Enable on bootSymlink by conventionsystemctl enable
systemctl daemon-reload                  # after editing a unit file
systemctl enable --now api.service
systemctl status api.service
systemctl restart api.service
systemctl list-dependencies api.service

journalctl -u api.service -f             # follow one service
journalctl -u api.service --since "1 hour ago" -p err

Targets and troubleshooting a boot

  • A target is a group of units; multi-user.target replaces run level 3 and graphical.target replaces run level 5.
  • systemctl set-default multi-user.target changes the default boot target.
  • systemctl rescue and systemctl emergency bring up a minimal environment for repair.
  • A failing unit does not necessarily stop the boot; check systemctl --failed rather than assuming success.
  • Boot parameters can disable a service or drop to a shell: systemd.unit=rescue.target, single or rd.break.
systemctl --failed
systemctl list-units --state=failed
systemctl cat api.service                # the effective unit plus drop-ins
systemctl show api.service -p Environment -p Restart

# a temporary override rather than editing the packaged unit
# systemctl edit api.service
💡
Use systemctl edit to add a drop-in override instead of modifying a unit that the package manager owns. Upgrades will overwrite your changes to the original file, and the failure appears weeks later during an unrelated update.

FAQ

Why does my service work when started by hand but fail at boot?
Almost always a missing dependency or environment. The interactive shell provides a PATH, a working directory and a network that are not present at boot; declare them in the unit.
How do I see why a service failed to start?
systemctl status shows the last lines, and journalctl -u name -b shows the full output from this boot including the exit code.

What an operating system does Containers, namespaces and cgroups

Last refreshed 2026-09-18.