Linux Systemd Targets vs Traditional Runlevels
Modern Linux distributions have largely replaced legacy SysVinit
runlevels with systemd targets to manage system initialization and
operating states. While traditional runlevels relied on sequentially
numbered operational modes (from 0 to 6) controlled by shell scripts,
systemd organizes boot states as .target unit files. This
article explains how targets like multi-user.target
function, how they map to legacy runlevels, and how systemd orchestrates
dependencies, parallel services, and administrative transitions between
different system states.
The Shift from Runlevels to Targets
In the traditional SysVinit architecture, runlevels represented predefined static operating modes:
- Runlevel 0: Halt / Shut down
- Runlevel 1 / S: Single-user / Maintenance mode
- Runlevel 2: Multi-user mode without networking (on some distributions)
- Runlevel 3: Full multi-user mode with networking (non-graphical console)
- Runlevel 4: Unused / User-definable
- Runlevel 5: Multi-user mode with networking and display manager (GUI)
- Runlevel 6: Reboot
SysVinit processed these runlevels sequentially. Scripts prefixed
with S (start) or K (kill) in directories like
/etc/rc3.d/ executed in numeric order. This linear model
introduced boot bottlenecks and lacked nuanced dependency
resolution.
Systemd modernized this mechanism by treating operating states as
target units (.target). A target does not execute code
directly; instead, it serves as an aggregation point and synchronization
anchor for services, sockets, mount points, and other targets.
Mapping Runlevels to Systemd Targets
To maintain backward compatibility, systemd defines exact equivalents and symlinks for historical runlevels:
| Traditional Runlevel | Systemd Target Unit | Description |
|---|---|---|
| Runlevel 0 | poweroff.target |
Shuts down and powers off the system |
| Runlevel 1 | rescue.target |
Minimal base system and single-user shell |
| Runlevel 2, 3, 4 | multi-user.target |
Non-graphical multi-user environment with networking |
| Runlevel 5 | graphical.target |
Multi-user environment with GUI and display manager |
| Runlevel 6 | reboot.target |
Shuts down and reboots the system |
| Emergency Mode | emergency.target |
Minimal console with root file system mounted read-only |
Legacy tools such as telinit 3 or init 5
still function on systemd-based distributions because systemd maps those
commands to target activations behind the scenes.
How multi-user.target Operates
The multi-user.target is the standard operational state
for headless servers and CLI workstations. Rather than running a static
sequence of numbered scripts, systemd evaluates the target’s dependency
tree:
- Dependency Definitions: Units declare their
association with a target using configuration directives such as
Wants=,Requires=, andPartOf=. For instance, networking services, SSH daemons, and system loggers declareWantedBy=multi-user.targetin their[Install]sections. - File System Symlinks: When a service is enabled via
systemctl, systemd creates a symbolic link to the unit file inside
/etc/systemd/system/multi-user.target.wants/. At boot time, reachingmulti-user.targetentails pulling in every unit linked in this directory. - Parallel Execution: Systemd parses ordering
dependencies (
Before=andAfter=). If two services depend onmulti-user.targetbut not on each other, systemd starts them simultaneously, drastically reducing system boot times compared to SysVinit. - Target Hierarchy: Targets can inherit from other
targets. For example,
graphical.targetincludesmulti-user.targetas a prerequisite, which in turn depends onbasic.target,sysinit.target, andlocal-fs.target.
Managing Targets with Systemctl
System administrators interact with system targets using the
systemctl utility rather than editing configuration files
manually.
Checking the Default Target
To view which target activates automatically at boot:
systemctl get-defaultChanging the Default Boot Target
To switch a system permanently from a graphical desktop to a command-line interface:
sudo systemctl set-default multi-user.targetThis command updates the symbolic link located at
/etc/systemd/system/default.target to point directly to
/lib/systemd/system/multi-user.target.
Switching Targets at Runtime
To change the system state immediately without rebooting, use the
isolate command:
sudo systemctl isolate multi-user.targetThe isolate operation acts like changing runlevels in
SysVinit. Systemd stops all services that are not required by
multi-user.target (such as Xorg, Wayland, or desktop
display managers like GDM/LightDM) and starts any missing services
defined under the target.
Inspecting Target Dependencies
To visualize all units required or pulled in by
multi-user.target:
systemctl list-dependencies multi-user.targetThis hierarchical view allows administrators to audit precisely which services participate in bringing the system into its operational multi-user state.