LFCS 69 🐧 System Targets
Systemd targets are the replacement for SysV runlevels. They are synchronization points that group units together, defining what services and capabilities the system should have at a given stage of boot or operation . For the LFCS exam, the key distinction is between the default target (what the system boots into next time) and the active target (what the system is doing right now). Confusing the two leads to changes that appear to do nothing until a reboot, or temporary switches that are mistakenly believed to be permanent.
This chapter covers the target hierarchy, the mapping between common targets and their legacy runlevel equivalents, the commands that inspect and change targets, and the difference between setting a default and isolating a running system.
Key point: systemctl set-default changes the symlink at /etc/systemd/system/default.target for the next boot. systemctl isolate switches the running system immediately. Neither command does both.
Why targets exist
The runlevel abstraction problem. SysV runlevels were numbered 0 through 6, and each number had a loosely defined meaning: 3 for text multiuser, 5 for graphical. The meanings were conventions, not enforced contracts, and the numeric labels carried no inherent logic. Systemd targets replace this with named units that describe their purpose: multi-user.target, graphical.target, rescue.target. The name states the capability, and the unit file defines the dependencies .
The synchronization problem. During boot, some services must start before others. A network-dependent service needs the network stack to be up. A display manager needs the filesystem and basic services. Targets provide named synchronization points that units can order themselves against using After= and Wants= dependencies . This is more flexible than runlevel numbers because a unit can depend on multiple targets and targets can be layered.
The troubleshooting problem. When a system fails to reach its default target, an administrator needs a minimal environment to diagnose the issue. rescue.target and emergency.target provide graduated levels of minimal service. Rescue mounts local filesystems and starts a root shell; emergency mounts root read-only and starts almost nothing. These targets exist specifically for recovery scenarios .
The compatibility problem. Existing documentation, scripts, and administrator habits refer to runlevels. Systemd provides runlevel0.target through runlevel6.target as symbolic links to the corresponding named targets, so legacy references continue to work . This compatibility layer does not change the underlying model; it translates it.
a. The Target Hierarchy and Common Targets
Targets are layered. graphical.target pulls in multi-user.target, which pulls in basic.target, which pulls in sysinit.target. A system that reaches graphical.target has also satisfied everything required by the targets beneath it. This means isolating a higher target starts more services, and isolating a lower target stops the services that the lower target does not require.
The commonly used targets and their runlevel equivalents are:
| Target | Runlevel Equivalent | Purpose |
|---|---|---|
poweroff.target | runlevel0.target | Shut down and power off |
rescue.target | runlevel1.target | Single-user rescue shell |
multi-user.target | runlevel2/3/4.target | Non-graphical multiuser with networking |
graphical.target | runlevel5.target | Multiuser with display manager |
reboot.target | runlevel6.target | Shut down and reboot |
The runlevel* targets are symbolic links, not independent units. They exist for compatibility and resolve to the named targets . On a typical server, the default is multi-user.target; on a desktop, it is graphical.target.
# Show the current default target
systemctl get-default
# List all currently active targets
systemctl list-units --type=target
The second command is important because more than one target can be active at once. A system at graphical.target also has multi-user.target and basic.target active, because the higher target pulled them in. Asking “what is the current runlevel” is therefore ambiguous; asking “which targets are active” is precise .
b. Inspecting and Changing the Default Target
The default target is controlled by a symlink at /etc/systemd/system/default.target. The systemctl get-default command reads this symlink and reports the target name. The systemctl set-default command rewrites it .
# Set the system to boot into text mode on next reboot
sudo systemctl set-default multi-user.target
# Set the system to boot into graphical mode on next reboot
sudo systemctl set-default graphical.target
The output of set-default shows the symlink change explicitly: it removes the old default.target link and creates a new one pointing to the chosen target . This is a persistent change, but it does not affect the currently running system. The new target takes effect at the next boot.
A common LFCS trap is running set-default and expecting the system to switch immediately. It will not. The change is written to disk and waits for a reboot. To switch the running system, a different command is required.
c. Isolating a Target for the Running System
systemctl isolate starts the named target and stops all units that are not required by it. This is the runtime equivalent of switching runlevels. It is immediate and temporary; it does not change the default for the next boot .
# Switch the running system to graphical mode immediately
sudo systemctl isolate graphical.target
# Switch the running system to rescue mode immediately
sudo systemctl isolate rescue.target
isolate should be used with care on remote systems. Isolating rescue.target stops networking and the SSH daemon, which terminates the remote session. Isolating multi-user.target from a graphical session closes the display manager and all graphical applications. The command is powerful and immediate, which is exactly why it is distinct from set-default.
The relationship between the two commands is the most testable point in this objective:
# Temporary: changes the running state now, reverts on reboot
sudo systemctl isolate multi-user.target
# Persistent: changes the next boot state, no effect now
sudo systemctl set-default multi-user.target
Complete Example Session
# ============================================
# PART 1: CHECK THE CURRENT DEFAULT TARGET
# ============================================
# This reads /etc/systemd/system/default.target symlink
systemctl get-default
# Typical server output: multi-user.target
# Typical desktop output: graphical.target
# ============================================
# PART 2: LIST ALL ACTIVE TARGETS
# ============================================
# Multiple targets are active simultaneously
systemctl list-units --type=target
# You will see graphical.target, multi-user.target, basic.target, etc.
# ============================================
# PART 3: CHANGE DEFAULT TO TEXT MODE
# ============================================
# Persistent change: next boot will be text-only
sudo systemctl set-default multi-user.target
# Output shows symlink replacement
# ============================================
# PART 4: VERIFY THE DEFAULT CHANGE
# ============================================
# Confirm the symlink now points to multi-user.target
systemctl get-default
# The running system has NOT changed yet
# ============================================
# PART 5: TEMPORARILY ISOLATE GRAPHICAL MODE
# ============================================
# Immediate switch without changing the default
sudo systemctl isolate graphical.target
# The display manager starts now, but next boot is still text mode
# ============================================
# PART 6: CHECK THE DEFAULT AFTER ISOLATION
# ============================================
# Default is still multi-user.target despite running graphical
systemctl get-default
# This is the key distinction: isolate does not change default
# ============================================
# PART 7: RESTORE DEFAULT TO GRAPHICAL
# ============================================
# If the system should boot to GUI again
sudo systemctl set-default graphical.target
# ============================================
# PART 8: EXAMINE TARGET DEPENDENCIES
# ============================================
# See what graphical.target requires
systemctl list-dependencies graphical.target
# multi-user.target appears as a dependency
# ============================================
# PART 9: RESCUE MODE FOR TROUBLESHOOTING
# ============================================
# Rescue requires root password, mounts local filesystems
# Switch to it only if you have console access
sudo systemctl isolate rescue.target
# ============================================
# PART 10: EMERGENCY MODE FOR CRITICAL RECOVERY
# ============================================
# Emergency mounts root read-only, almost no services
# Useful for repairing a broken /etc/fstab
# At GRUB, append: systemd.unit=emergency.target
# Or from a running system (not recommended remotely):
# sudo systemctl isolate emergency.target
The ten parts demonstrate the distinction between persistent and temporary target changes. Part 3 changes the default. Part 5 changes the running state. Part 6 proves they are independent. This is the core exam skill.
Quick Reference
Common Targets and Runlevel Equivalents
| Target | Runlevel | Purpose |
|---|---|---|
poweroff.target | runlevel0.target | Power off |
rescue.target | runlevel1.target | Single-user rescue |
multi-user.target | runlevel3.target | Text multiuser |
graphical.target | runlevel5.target | Graphical login |
reboot.target | runlevel6.target | Reboot |
emergency.target | (no runlevel) | Minimal recovery shell |
Target Commands
| Command | Effect | Persistent? |
|---|---|---|
systemctl get-default | Show default target | N/A |
systemctl set-default <target> | Change default for next boot | Yes |
systemctl isolate <target> | Switch running system now | No |
systemctl list-units --type=target | Show active targets | N/A |
systemctl list-dependencies <target> | Show target requirements | N/A |
Default Target Symlink
| Item | Value |
|---|---|
| Symlink location | /etc/systemd/system/default.target |
| Target unit files | /usr/lib/systemd/system/*.target |
| Runlevel compatibility | runlevelN.target symlinks to named target |
Best Practices
✅ Do This:
# Check current default before changing
systemctl get-default # ✅
# Use set-default for permanent boot mode change
sudo systemctl set-default multi-user.target # ✅
# Use isolate for temporary mode switch
sudo systemctl isolate rescue.target # ✅
# Verify multiple active targets, not a single "runlevel"
systemctl list-units --type=target # ✅
# Use emergency.target only with console access
# systemd.unit=emergency.target on kernel command line # ✅
❌ Don’t Do This:
# Expect set-default to change the running system
sudo systemctl set-default multi-user.target # ❌ (no immediate effect)
# Expect isolate to persist across reboot
sudo systemctl isolate multi-user.target # ❌ (temporary only)
# Isolate rescue.target on a remote SSH session
sudo systemctl isolate rescue.target # ❌ (kills networking/SSH)
# Assume only one target is active
# graphical.target implies multi-user.target is also active # ❌
# Edit /etc/systemd/system/default.target manually
# Use set-default; manual edits bypass validation # ❌
Common Pitfalls
| Pitfall | Why It Happens | Fix |
|---|---|---|
set-default appears to do nothing | It only affects next boot | Reboot, or use isolate for immediate change |
isolate lost after reboot | It is temporary by design | Use set-default for persistence |
Remote session drops during isolate | Rescue stops networking | Use console access or avoid remote isolate |
| Target name not found | Typo or non-existent target | Verify with systemctl list-unit-files --type=target |
| Multiple targets active, confusion | Higher targets pull in lower ones | Use list-dependencies to see the chain |
Real-World Examples
1. Check Default Target
systemctl get-default
2. Change Default to Text Mode
sudo systemctl set-default multi-user.target
3. Change Default to GUI
sudo systemctl set-default graphical.target
4. Switch to Rescue Immediately
sudo systemctl isolate rescue.target
5. Switch to Graphical Immediately
sudo systemctl isolate graphical.target
6. List Active Targets
systemctl list-units --type=target
7. Show Target Dependencies
systemctl list-dependencies multi-user.target
8. Boot to Emergency from GRUB
systemd.unit=emergency.target
9. Check Runlevel Compatibility Link
ls -l /usr/lib/systemd/system/runlevel5.target
10. Verify Symlink After Change
ls -l /etc/systemd/system/default.target
Visual
Default vs. Active Target
┌──────────────────────────────────────────────────────────────┐
│ SET-DEFAULT ISOLATE │
│ │
│ Changes: Changes: │
│ /etc/systemd/system/ Running system state │
│ default.target symlink │
│ │
│ Affects: Affects: │
│ Next boot Current session │
│ │
│ Persists: Persists: │
│ Yes No (reverts on reboot) │
│ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ set-default │ │ isolate │ │
│ │ multi-user │ │ graphical │ │
│ └────────┬────────┘ └────────┬────────┘ │
│ │ │ │
│ ▼ ▼ │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Next boot: │ │ Now: │ │
│ │ text mode │ │ GUI starts │ │
│ │ │ │ Default still │ │
│ │ Running system: │ │ text mode │ │
│ │ unchanged │ │ │ │
│ └─────────────────┘ └─────────────────┘ │
│ │
│ Two different commands for two different needs. │
│ │
└──────────────────────────────────────────────────────────────┘
Target Dependency Chain
┌──────────────────────────────────────────────────────────────┐
│ graphical.target │
│ ┌─────────────────────────────────────────┐ │
│ │ Requires: multi-user.target │ │
│ │ Starts: display manager (gdm, sddm) │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ multi-user.target │
│ ┌─────────────────────────────────────────┐ │
│ │ Requires: basic.target │ │
│ │ Starts: network, multiuser services │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ basic.target │
│ ┌─────────────────────────────────────────┐ │
│ │ Requires: sysinit.target │ │
│ │ Starts: sockets, timers, paths │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ sysinit.target │
│ ┌─────────────────────────────────────────┐ │
│ │ Early boot: udev, filesystem mounts │ │
│ └─────────────────────────────────────────┘ │
│ │
│ Isolating a higher target also satisfies lower targets. │
│ Isolating a lower target stops services above it. │
│ │
└──────────────────────────────────────────────────────────────┘
Runlevel Compatibility
┌──────────────────────────────────────────────────────────────┐
│ LEGACY NAME SYMLINK TARGET │
│ │
│ runlevel0.target ────► poweroff.target │
│ runlevel1.target ────► rescue.target │
│ runlevel2.target ────► multi-user.target │
│ runlevel3.target ────► multi-user.target │
│ runlevel4.target ────► multi-user.target │
│ runlevel5.target ────► graphical.target │
│ runlevel6.target ────► reboot.target │
│ │
│ The runlevel targets are symlinks, not independent units. │
│ They exist for compatibility with older documentation │
│ and scripts. │
│ │
│ Modern commands use the named targets. │
│ │
└──────────────────────────────────────────────────────────────┘
Recovery Target Selection
┌──────────────────────────────────────────────────────────────┐
│ BOOT FAILURE? │
│ │
│ ┌─────────────────┐ │
│ │ Can reach │────► Use rescue.target │
│ │ multi-user? │ Root shell, local FS mounted │
│ └────────┬────────┘ Networking stopped │
│ │ NO │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Can mount root? │────► Use emergency.target │
│ │ │ Root read-only, minimal services │
│ └────────┬────────┘ For fstab repair │
│ │ NO │
│ ▼ │
│ ┌─────────────────┐ │
│ │ Use initramfs │ Root cannot be found │
│ │ shell or GRUB │ Storage driver missing │
│ └─────────────────┘ │
│ │
│ Each level provides less capability than the one above. │
│ Choose the highest that works for the repair needed. │
│ │
└──────────────────────────────────────────────────────────────┘
Summary
| Item | Value |
|---|---|
| Target concept | Named grouping of units; replaces runlevels |
| Default target command | systemctl get-default |
| Change default | systemctl set-default <target> (persistent) |
| Switch running system | systemctl isolate <target> (temporary) |
| Default symlink | /etc/systemd/system/default.target |
| Text mode target | multi-user.target (runlevel 3 equivalent) |
| GUI target | graphical.target (runlevel 5 equivalent) |
| Rescue target | rescue.target (single-user, root shell) |
| Emergency target | emergency.target (root read-only, minimal) |
| Active targets | Multiple at once; use list-units --type=target |
Key takeaways:
set-defaultchanges the next boot;isolatechanges now. These are separate commands with separate effects. A change made with one is not visible in the other until the appropriate condition (reboot or current session) is met .- More than one target is active.
graphical.targetpulls inmulti-user.target, which pulls inbasic.target. Asking “what is the current runlevel” is less useful than listing active targets withsystemctl list-units --type=target. - Runlevel targets are compatibility symlinks.
runlevel3.targetpoints tomulti-user.target. Legacy references work, but the named target is the canonical form . - Rescue and emergency are graduated recovery modes. Rescue mounts local filesystems and provides a root shell. Emergency mounts root read-only and starts almost nothing. Use the highest level that allows the repair.
- Isolating rescue on a remote system terminates connectivity. Networking stops, and so does SSH. Rescue and emergency are console-level operations.
Remember: Systemd targets answer the question “what should this system be capable of?” The default target is the answer for the next boot. The active targets are the answer for right now. The two are connected by the symlink at /etc/systemd/system/default.target, but they are changed by different commands. set-default edits the symlink. isolate starts and stops units. An administrator who changes the default and sees no effect has not failed; they have simply changed the future rather than the present. For the LFCS exam, knowing which command changes which, and why, is the objective.
Stop using slow, ad-bloated tool sites! 🤮
🔎 Search “KandZ Tools” on Google to use many professional utilities for free.
KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)
⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free
🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!