Table of Contents
-
- What Are Targets?
- Target Files and Locations
- System vs. User Targets
-
- Core Targets Explained
- Default Dependencies
-
Customizing Targets: Practical Guide
- Modifying Existing Targets with Drop-In Files
- Creating New Targets from Scratch
-
Advanced Customization Techniques
- Target Priorities and Isolation
- Overriding the Default Target
- Masking and Disabling Targets
- User-Level Targets
Understanding Systemd Targets
What Are Targets?
A target is a systemd unit (file extension .target) that does not execute code directly. Instead, it acts as a “meta-unit” by grouping other units (services, sockets, mounts) and defining dependencies between them. Targets coordinate when units start, ensuring the system reaches a specific state (e.g., “graphical desktop” or “emergency shell”).
For example:
multi-user.targetactivates a multi-user command-line environment (no GUI).graphical.targetbuilds onmulti-user.targetby adding a graphical desktop.
Target Files and Locations
Systemd targets are defined in plaintext files. Their location determines their purpose:
| Path | Purpose |
|---|---|
/usr/lib/systemd/system/ | Distribution/default targets: Provided by packages (e.g., systemd itself). Modifying these directly is discouraged (updates may overwrite changes). |
/etc/systemd/system/ | Administrator-defined targets: Custom targets or overrides for system-wide use. This is where you should make changes. |
~/.config/systemd/user/ | User-specific targets: For per-user services (e.g., user-level daemons). |
System vs. User Targets
- System targets (in
/etc/systemd/system/) manage system-wide state and require root privileges to modify. - User targets (in
~/.config/systemd/user/) control user-specific services (e.g., starting a background music player when the user logs in) and do not require root.
Common Systemd Targets
Understanding default targets is key to customization. Below are essential targets and their roles:
Core Targets
| Target | Purpose | Key Dependencies |
|---|---|---|
poweroff.target | Shuts down the system. | final.target, umount.target |
reboot.target | Reboots the system. | final.target, umount.target |
emergency.target | Minimal emergency shell (only root, no networking/filesystems). | sysinit.target, emergency.service |
rescue.target | Rescue shell with basic services (networking, filesystems). | multi-user.target, rescue.service |
multi-user.target | Multi-user command-line environment (default for servers). | basic.target, network.target, sshd.service (if installed) |
graphical.target | Graphical desktop environment (default for desktops). | multi-user.target, display-manager.service (e.g., GDM, LightDM) |
Default Target Behavior
Most systems boot to a default target (e.g., graphical.target for desktops). Check the default with:
systemctl get-default
Customizing Targets: Practical Guide
Customizing targets lets you tailor system behavior. We’ll cover two scenarios: modifying existing targets and creating new ones.
Modifying Existing Targets
To avoid overwriting distribution-provided targets, use drop-in files in /etc/systemd/system/[target].target.d/. Drop-ins override specific settings of the original target without replacing the entire file.
Example: Adding a Service to multi-user.target
Suppose you want a custom backup service (my-backup.service) to start automatically when the system reaches multi-user.target.
Step 1: Create a drop-in directory for multi-user.target
sudo mkdir -p /etc/systemd/system/multi-user.target.d/
Step 2: Create a drop-in file
Create /etc/systemd/system/multi-user.target.d/backup.conf with:
[Unit]
# Ensure my-backup.service starts after multi-user.target’s dependencies
After=network.target
# Require my-backup.service to run (fail target if service fails)
Requires=my-backup.service
Step 3: Reload systemd and test
sudo systemctl daemon-reload
sudo systemctl restart multi-user.target
Now my-backup.service will start whenever multi-user.target is activated.
Creating New Targets
Create a new target when existing targets don’t meet your needs (e.g., a “kiosk mode” that runs only a GUI app, or a “minimal server” with no extra services).
Example: Kiosk Target
Let’s create a kiosk.target that starts a fullscreen web browser (e.g., Chromium) and nothing else (no login prompts, no extra services).
Step 1: Create the target file
Create /etc/systemd/system/kiosk.target with:
[Unit]
Description=Kiosk Mode (Fullscreen Browser)
Documentation=man:systemd.target(5)
# Start after graphical.target (to ensure GUI is ready)
After=graphical.target
# Require graphical.target (fail if GUI doesn’t start)
Requires=graphical.target
# Conflict with login managers (no tty1 login prompt)
Conflicts[email protected]
[Install]
# Make this target available as a default
WantedBy=default.target
Alias=kiosk
Step 2: Create a service for the kiosk app
Create /etc/systemd/system/kiosk-browser.service to launch Chromium:
[Unit]
Description=Kiosk Browser (Chromium)
After=graphical.target
[Service]
User=kiosk-user # Dedicated user for the kiosk
ExecStart=/usr/bin/chromium-browser --kiosk https://example.com
Restart=always # Restart if browser crashes
[Install]
WantedBy=kiosk.target # Start when kiosk.target is activated
Step 3: Enable and set as default
# Enable the browser service
sudo systemctl enable kiosk-browser.service
# Set kiosk.target as the default boot target
sudo systemctl set-default kiosk.target
# Reboot to test
sudo reboot
The system will now boot directly into a fullscreen browser.
Advanced Customization Techniques
Target Priorities and Isolation
- Default Dependencies: Most targets include
DefaultDependencies=yes, which automatically adds dependencies onbasic.target(core system services). SetDefaultDependencies=noto build a minimal target from scratch. - Isolating Targets: Use
systemctl isolate [target]to switch the system to a target immediately (e.g.,systemctl isolate rescue.targetfor rescue mode). - Priority: Use
Before=/After=in the[Unit]section to control order (e.g.,After=network.targetensures a target starts after networking).
Overriding the Default Target
Change the default boot target with:
# Set graphical.target as default (desktop)
sudo systemctl set-default graphical.target
# Set multi-user.target as default (server)
sudo systemctl set-default multi-user.target
# Set our custom kiosk.target as default
sudo systemctl set-default kiosk.target
Masking Targets
To prevent a target from ever activating (e.g., blocking graphical.target on a server), mask it:
sudo systemctl mask graphical.target
Unmask with:
sudo systemctl unmask graphical.target
User-Level Targets
Customize per-user environments with targets in ~/.config/systemd/user/. For example, start a music player when you log in:
-
Create
~/.config/systemd/user/music.target:[Unit] Description=User Music Target After=default.target [Install] WantedBy=default.target -
Create a service
~/.config/systemd/user/music-player.serviceand enable it formusic.target.
Troubleshooting Target Configuration
Common Issues and Fixes
| Issue | Fix |
|---|---|
| Target fails to start | Check dependencies with systemctl list-dependencies [target]. |
| Service not starting with target | Verify the service’s WantedBy=/RequiredBy= points to the target. |
| Conflicts with other units | Use Conflicts= in the target file to block unwanted units. |
Key Commands for Debugging
-
List all active targets:
systemctl list-units --type=target --state=active -
Check target status:
systemctl status kiosk.target -
Verify target file syntax:
systemd-analyze verify /etc/systemd/system/kiosk.target -
View target logs:
journalctl -u kiosk.target -b # Logs from current boot
Conclusion
Systemd targets are the backbone of system state management in Linux. By customizing targets—whether modifying existing ones with drop-in files or creating new ones—you can tailor your system to specific use cases, from minimal servers to specialized kiosks.
Start small: experiment with drop-in files to tweak existing targets before creating complex custom targets. Always test changes in a non-production environment, and use systemd-analyze and journalctl to debug issues.