funwithlinux guide

Customizing the Target Configuration in Systemd

Systemd has become the de facto init system for most modern Linux distributions, replacing traditional SysVinit and Upstart. At its core, systemd manages system state through **targets**—units that group other systemd units (services, sockets, mounts, etc.) to define specific operational modes (e.g., multi-user command-line, graphical desktop, rescue mode). Think of targets as "system states" or "runlevels 2.0": they determine which services and resources are active when the system boots or transitions between modes. Customizing targets is a powerful way to tailor your system’s behavior. Whether you’re building a minimal server, a kiosk system, or a specialized embedded device, understanding how to modify or create targets lets you control exactly what runs (and what doesn’t) in each state. This blog will guide you through the fundamentals of systemd targets, common use cases, and step-by-step customization techniques.

Table of Contents

  1. Understanding Systemd Targets

    • What Are Targets?
    • Target Files and Locations
    • System vs. User Targets
  2. Common Systemd Targets

    • Core Targets Explained
    • Default Dependencies
  3. Customizing Targets: Practical Guide

    • Modifying Existing Targets with Drop-In Files
    • Creating New Targets from Scratch
  4. Advanced Customization Techniques

    • Target Priorities and Isolation
    • Overriding the Default Target
    • Masking and Disabling Targets
    • User-Level Targets
  5. Troubleshooting Target Configuration

  6. Conclusion

  7. References

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.target activates a multi-user command-line environment (no GUI).
  • graphical.target builds on multi-user.target by adding a graphical desktop.

Target Files and Locations

Systemd targets are defined in plaintext files. Their location determines their purpose:

PathPurpose
/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

TargetPurposeKey Dependencies
poweroff.targetShuts down the system.final.target, umount.target
reboot.targetReboots the system.final.target, umount.target
emergency.targetMinimal emergency shell (only root, no networking/filesystems).sysinit.target, emergency.service
rescue.targetRescue shell with basic services (networking, filesystems).multi-user.target, rescue.service
multi-user.targetMulti-user command-line environment (default for servers).basic.target, network.target, sshd.service (if installed)
graphical.targetGraphical 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 on basic.target (core system services). Set DefaultDependencies=no to 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.target for rescue mode).
  • Priority: Use Before=/After= in the [Unit] section to control order (e.g., After=network.target ensures 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:

  1. Create ~/.config/systemd/user/music.target:

    [Unit]  
    Description=User Music Target  
    After=default.target  
    
    [Install]  
    WantedBy=default.target  
  2. Create a service ~/.config/systemd/user/music-player.service and enable it for music.target.

Troubleshooting Target Configuration

Common Issues and Fixes

IssueFix
Target fails to startCheck dependencies with systemctl list-dependencies [target].
Service not starting with targetVerify the service’s WantedBy=/RequiredBy= points to the target.
Conflicts with other unitsUse 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.

References