In the world of systemd, target units play a critical role in orchestrating the state of a Linux system. While services do the actual work, targets define the bigger picture: when and in what context those services should run. Think of them as milestones or checkpoints in the boot process — or custom-defined states that bundle related units together.
In this article, we’ll demystify systemd targets, explore their role, explain how to create custom targets, and show real-world examples where custom targets provide meaningful improvements in system management.
What is a Target Unit?
A target unit is a systemd unit of type .target. Its main purpose is to group and synchronize other units. Targets don’t do anything directly — they’re placeholders for sets of units (services, sockets, devices, etc.) that should start or stop together.
They are also used to express a system’s state. For example:
basic.target: Minimal system initializationmulti-user.target: Text-based system fully operationalgraphical.target: GUI session readyrescue.target: Emergency shell with minimal services
Anatomy of a Target Unit
A typical target unit file is quite simple:
[Unit]
Description=My Custom Target
Requires=my-custom-service.service
After=network.target
[Install]
WantedBy=multi-user.target
Where:
Requires=: Units that must be activated when this target is activatedAfter=: Defines the order — ensures this target starts after the listed unitWantedBy=: Allows the target to be enabled viasystemctl enable
Targets vs Runlevels
If you’re coming from the SysVinit world, some targets replace* the old runlevel system:
| Runlevel | systemd Equivalent |
|---|---|
| 0 | poweroff.target |
| 1 | rescue.target |
| 3 | multi-user.target |
| 5 | graphical.target |
| 6 | reboot.target |
* Not every systemd target unit can be used like a runlevel — only those with the AllowIsolate option set to yes.
You can change the default target (equivalent to default runlevel) like so:
sudo systemctl set-default multi-user.target
Common Built-in Targets
default.target
The default system state — typically graphical.target or multi-user.target.
network.target
Used to order units that require basic network availability. Not guaranteed to mean full connectivity.
network-online.target
Stronger than network.target — it ensures full network connectivity (used in server services).
multi-user.target
System is up and running in a non-graphical, multi-user mode.
graphical.target
All of multi-user.target plus graphical environment (X, Wayland, etc.).
rescue.target and emergency.target
Used for recovery and troubleshooting. Minimal services and user intervention possible.
Creating a Custom Target
Let’s say you want to boot your system into a special “Maintenance Mode” that only starts SSH and a monitoring agent.
Step 1: Define the Target
sudo nano /etc/systemd/system/maintenance.target
[Unit]
Description=Maintenance Mode
Requires=ssh.service monitoring-agent.service
After=network.target
[Install]
WantedBy=multi-user.target
Step 2: Enable and Use It
sudo systemctl daemon-reexec
sudo systemctl enable maintenance.target
sudo systemctl isolate maintenance.target
This tells systemd to stop all other units not required by maintenance.target and switch the system state accordingly.
Some Real-World Use Cases
Case 1: Safe Maintenance Boot
Create a custom target that disables user apps but enables SSH and logging. Perfect for system maintenance or updates.
Case 2: Boot Mode for Backup
Have a system boot into a backup target where only the backup agent and a safe read-only environment are available.
Case 3: Fast Boot for Headless Devices
Create a stripped-down target for embedded or IoT systems — load only essential networking, logging, and app services.
Case 4: Developer Mode
Define a target that launches dev tools, test databases, and editors, isolated from production services.
Inspecting Targets
List all loaded targets:
systemctl list-units --type=target
Show dependencies:
systemctl list-dependencies graphical.target
Show the current active target:
systemctl get-default
Switch to a new target:
sudo systemctl isolate rescue.target
Pro Tips
- Always include
After=andRequires=orWants=to manage timing and dependencies. - Use
PartOf=if you want a service to be stopped when a target is stopped. - Use
isolatewith caution — it stops everything not part of the new target. - Don’t forget
WantedBy=in[Install]to allow enabling the target.
Final Thoughts
Targets in systemd aren’t just a modern replacement for runlevels — they’re a powerful way to group, order, and manage system states. Whether you’re trying to define a minimal environment, a special-purpose boot mode, or a group of logically related services, targets give you a clean, modular way to do it.
The more you embrace targets, the more maintainable and understandable your system configuration becomes. Create them with intent, document them clearly, and enjoy a more elegant Linux experience.
** Official documentation for systemd target units can be found here