Skip to main content
RunBook Academy

LinuxVII · systemd and Service ManagementArchitecture

systemd architecture — PID 1 and the unit model

Intermediate⏱ ~12 minbashsystemctlsystemd-analyzecat

What you'll learn

  • Explain systemd's role as PID 1 and the init system
  • Identify the unit types systemd manages
  • Trace the dependency graph between units
  • Locate unit files on the filesystem

Prerequisites

Verified against Ubuntu 24.04 LTS · Debian 12 (Bookworm) · RHEL 9.x · Rocky Linux 9.x · AlmaLinux 9.x · Linux kernel 6.1 LTS / 6.6 LTS · systemd 255+ · OpenSSH 8.7p1 (RHEL 9) / 9.6p1 (Ubuntu 24.04) · nftables 1.0.x · chrony 4.x · Pacemaker 2.1.x · Corosync 3.1.x · 2026-08-09

Not yet marked complete on this device.

systemd is the init system on every major Linux distribution. It runs as PID 1, manages every other process on the system, and owns the dependency graph that determines start and stop order. Understanding systemd is non-negotiable for production Linux.

Why PID 1 matters

When the Linux kernel finishes boot, it execs /sbin/init (or /lib/systemd/systemd on modern systems). This process becomes PID 1 and never exits — it owns the lifecycle of every other process.

PID 1 has two special properties:

  • It cannot be killed by SIGKILL or SIGSTOP. The kernel ignores these signals for PID 1 by design.
  • If PID 1 exits, the kernel panics. There is no userspace fallback.

On modern Linux, PID 1 is systemd. The kernel init= parameter can choose a different init, but doing so forfeits the entire userspace — every distribution assumes systemd.

Unit types

systemd manages the system through “units”. Each unit describes a resource: a service, a mount point, a socket, a timer, a device.

Unit typeSuffixPurpose
Service.serviceA daemon process
Socket.socketA listening socket that activates a service on connection
Mount.mountA filesystem mount point
Automount.automountAn on-demand mount
Swap.swapA swap device
Path.pathA file-system path monitored for changes
Timer.timerA timer that activates a service at a time or interval
Target.targetA grouping of units (like a runlevel)
Device.deviceA kernel-recognised device
Scope.scopeA group of externally-created processes
Slice.sliceA cgroup hierarchy node
Read-only / Safesystemctl list-units
$ systemctl list-units --type=service --state=running | head
UNIT                         LOAD   ACTIVE SUB     DESCRIPTION
accounts-daemon.service      loaded active running Accounts Service
chrony.service                loaded active running chrony, an NTP client/server
cron.service                  loaded active running Regular background program processing daemon
dbus.service                  loaded active running D-Bus System Message Bus
...

Illustrative output

Unit locations

Unit files live in three directories:

PathVendorOverride
/usr/lib/systemd/system/Distribution packagesDO NOT EDIT — overwritten by package updates
/etc/systemd/system/Local adminUse for host-specific overrides
/run/systemd/transient/RuntimeCreated by systemd-run; ephemeral

A unit can be replaced by a same-named file in a higher-priority directory. /etc/systemd/system overrides /usr/lib/systemd/system.

Read-only / SafeFragmentPath
$ systemctl show sshd.service -p FragmentPath
FragmentPath=/usr/lib/systemd/system/sshd.service

Illustrative output

Dependencies

Units declare dependencies on each other through directives in their [Unit] section:

DirectiveEffect on startEffect on stop
Requires=Start the dependency; if it fails and After= names it, this unit does not startUpwards, not downwards. If the DEPENDENCY is explicitly stopped or restarted, this unit is stopped or restarted too. Stopping this unit does not stop the dependency
Wants=Start the dependency as a soft preference(no effect)
Requisite=Like Requires, but the dependency must already be active(no effect)
BindsTo=Like Requires, but stronger — if the dependency is stopped, this unit is also stoppedStops together
PartOf=(no effect on start)When the LISTED unit is stopped or restarted, this unit is stopped/restarted too. One-way: changes to this unit do not affect the listed unit
Conflicts=Cannot be active at the same time(no effect)
Before=This unit is ordered before the named unit(no effect)
After=This unit is ordered after the named unit(no effect)
Read-only / Safelist-dependencies
$ systemctl list-dependencies sshd.service
sshd.service
● ├─system.slice
● ├─-.mount
● ├─network.target
● │ ├─NetworkManager.service
● │ └─network-online.target
● └─sysinit.target
●   ├─ apparmor.service
●   ├─ dev-hugepages.mount
●   ...

Illustrative output

Targets

Targets group units that should reach a particular state together. The classic runlevels are targets:

RunlevelTargetPurpose
0poweroff.targetHalt
1rescue.targetSingle-user mode
3multi-user.targetMulti-user, no GUI
5graphical.targetMulti-user, GUI
6reboot.targetReboot

The default.target is what the system boots into by default. It is usually a symlink to graphical.target or multi-user.target.

Read-only / Safedefault target
$ systemctl get-default; ls -l /etc/systemd/system/default.target
multi-user.target
lrwxrwxrwx 1 root root 36 Aug  9 11:11 /etc/systemd/system/default.target -> /usr/lib/systemd/system/multi-user.target

Illustrative output

Production discipline

  • Never edit /usr/lib/systemd/system/* — package updates overwrite it.
  • Edit /etc/systemd/system/* for host-specific overrides.
  • Use drop-ins (/etc/systemd/system/<unit>.d/override.conf) for partial overrides; the diff against the vendor file is clearer than a full replacement.
  • After every edit, run systemctl daemon-reload to make systemd re-read units.
  • After every enable/disable, verify with systemctl is-enabled <unit>.

Knowledge check

Knowledge check · 4 questions

  1. Q1. Which directory should you use for host-specific systemd unit overrides?

  2. Q2. PID 1 can be killed with SIGKILL.

  3. Q3. Which of the following are correct systemd practices? Select all that apply.

  4. Q4. Five worker services each declare PartOf=myapp.target. During a change window the operator runs `systemctl restart worker-1.service` to cycle the group, then later `systemctl stop myapp.target` believing the workers will keep running. What actually happens?

Passing score: 75%. Answers are checked in this browser.