funwithlinux guide

How to Configure and Manage Services with Systemd

Systemd is a system and service manager for Linux operating systems, widely adopted as the default init system (replacing legacy systems like SysVinit) in distributions such as Ubuntu, Fedora, Debian, and Red Hat Enterprise Linux (RHEL). It is responsible for initializing the system during boot, managing running processes (services), handling power management, and much more. What makes systemd powerful? Its key features include **parallel service startup** (faster boot times), **on-demand service activation**, **centralized logging** (via `journald`), and a unified configuration model for services, sockets, timers, and more. Whether you’re a system administrator or a Linux enthusiast, mastering systemd is critical for managing services effectively. This blog will guide you through the fundamentals of systemd, from understanding core concepts to configuring and managing services like a pro.

Table of Contents

  1. Understanding Systemd Basics
  2. Key Systemd Concepts
    • 2.1 Units
    • 2.2 Targets
    • 2.3 Services
  3. Managing Services with systemctl
    • 3.1 Starting, Stopping, and Restarting Services
    • 3.2 Enabling/Disabling Services (Boot Persistence)
    • 3.3 Checking Service Status
  4. Configuring Services: Unit Files
    • 4.1 Unit File Locations
    • 4.2 Anatomy of a Service Unit File
    • 4.3 Editing Unit Files (Overrides)
  5. Advanced Service Management
    • 5.1 Masking vs. Disabling Services
    • 5.2 Timers (Cron Alternatives)
    • 5.3 Service Dependencies
  6. Troubleshooting Services
    • 6.1 Checking Logs with journalctl
    • 6.2 Validating Unit Files
    • 6.3 Debugging Failed Services
  7. Conclusion
  8. References

1. Understanding Systemd Basics

At its core, systemd is designed to manage “units”—abstract resources that represent system components. It starts as the first process (PID 1) during boot and orchestrates the initialization of all other services and system components.

Why Systemd?

  • Faster Boot: Parallelizes service startup instead of sequential execution (unlike SysVinit).
  • Unified Management: Handles services, sockets, timers, and mounts through a single interface (systemctl).
  • On-Demand Activation: Starts services only when needed (e.g., when a network request arrives via a socket).
  • Centralized Logging: Uses journald to aggregate logs from services, kernel, and userspace.

2. Key Systemd Concepts

To work effectively with systemd, you need to understand three core concepts: units, targets, and services.

2.1 Units

A “unit” is the basic building block of systemd. It represents a resource to manage (e.g., a service, socket, or timer) and is defined by a unit file (a plaintext configuration file).

Common unit types include:

Unit TypeFile ExtensionPurpose
Service.serviceManages a daemon or application (e.g., nginx.service, sshd.service).
Target.targetGroups units to define system states (e.g., multi-user.target = text login).
Socket.socketControls network sockets; enables on-demand service activation.
Mount.mountManages filesystem mounts (e.g., /home.mount).
Timer.timerSchedules tasks (replaces cron for systemd-aware services).

2.2 Targets

Targets are special units that group other units to define system states (similar to SysVinit runlevels). For example:

  • multi-user.target: Boots the system to a multi-user command-line environment (no GUI).
  • graphical.target: Boots to a graphical desktop (depends on multi-user.target).
  • poweroff.target: Shuts down the system.

To list all targets, run:

systemctl list-targets  

2.3 Services

A “service” is the most common unit type (.service). It defines how to start, stop, or restart a daemon (e.g., Nginx, MySQL, or SSH). Service unit files contain instructions for systemd to manage the process, such as the executable path, user context, and restart policies.

3. Managing Services with systemctl

The systemctl command is the primary tool for interacting with systemd. It lets you start, stop, enable, disable, and check the status of services.

3.1 Starting, Stopping, and Restarting Services

Use these commands to control services in the current session (changes are not persistent across reboots):

CommandPurposeExample
systemctl start <service>Start a service.systemctl start nginx.service
systemctl stop <service>Stop a service.systemctl stop nginx.service
systemctl restart <service>Stop and restart a service.systemctl restart nginx.service
systemctl reload <service>Reload configuration without stopping.systemctl reload nginx.service (for Nginx config changes)

Note: The .service suffix is optional (systemd assumes it by default). For example, systemctl start nginx works the same as systemctl start nginx.service.

3.2 Enabling/Disabling Services (Boot Persistence)

To control whether a service starts automatically at boot (persistent across reboots):

CommandPurposeExample
systemctl enable <service>Enable service to start on boot.systemctl enable nginx
systemctl disable <service>Disable auto-start on boot.systemctl disable nginx
systemctl is-enabled <service>Check if a service is enabled.systemctl is-enabled nginxenabled

3.3 Checking Service Status

To verify if a service is running and view its status:

systemctl status nginx.service  

Sample output:

● nginx.service - A high performance web server and a reverse proxy server  
     Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)  
     Active: active (running) since Wed 2024-03-20 10:00:00 UTC; 5min ago  
       Docs: man:nginx(8)  
   Main PID: 1234 (nginx)  
      Tasks: 2 (limit: 1132)  
     Memory: 3.5M  
     CGroup: /system.slice/nginx.service  
             ├─1234 nginx: master process /usr/sbin/nginx -g daemon on; master_process on;  
             └─1235 nginx: worker process  

Key fields:

  • Loaded: Whether the unit file is loaded and enabled.
  • Active: Current state (e.g., active (running), inactive, failed).
  • Main PID: Process ID of the main service process.

4. Configuring Services: Unit Files

To customize how a service runs (e.g., change the user, set a restart policy, or modify the executable path), you’ll need to edit its unit file.

4.1 Unit File Locations

Systemd unit files are stored in three primary directories (in order of priority, from lowest to highest):

  1. /usr/lib/systemd/system/: Default location for vendor-provided units (e.g., from packages like nginx). Do not edit these directly—they may be overwritten during updates.
  2. /etc/systemd/system/: User-customized units. Use this for modified or new services.
  3. /run/systemd/system/: Runtime-generated units (temporary, not persistent across reboots).

4.2 Anatomy of a Service Unit File

A .service file has three main sections: [Unit], [Service], and [Install]. Here’s an example for Nginx (nginx.service):

[Unit]  
Description=A high performance web server and a reverse proxy server  
Documentation=man:nginx(8)  
After=network.target remote-fs.target nss-lookup.target  # Start AFTER these targets/services  

[Service]  
Type=forking  # Daemon forks a child process (common for traditional daemons)  
PIDFile=/run/nginx.pid  # Path to the PID file  
ExecStart=/usr/sbin/nginx -g "daemon on; master_process on;"  # Command to start the service  
ExecReload=/usr/sbin/nginx -s reload  # Command to reload config  
ExecStop=/usr/sbin/nginx -s stop  # Command to stop the service  
PrivateTmp=true  # Isolate /tmp for the service  

[Install]  
WantedBy=multi-user.target  # Enable this service when multi-user.target is active (boot default)  

Key [Service] Directives

Customize service behavior with these common directives:

  • ExecStart=<command>: The command to start the service (required).
  • ExecStop=<command>: Command to stop the service.
  • ExecReload=<command>: Command to reload configuration.
  • Restart=<policy>: When to restart the service (e.g., always, on-failure, no).
    • Restart=on-failure: Restart if the service exits with a non-zero status (useful for critical services).
  • RestartSec=<seconds>: Delay before restarting (e.g., RestartSec=5 for 5 seconds).
  • User=<user>/Group=<group>: Run the service as a specific user/group (e.g., User=nginx).
  • WorkingDirectory=<path>: Set the working directory for the service.
  • Environment=<KEY>=<VALUE>: Set environment variables (e.g., Environment="PORT=8080").

4.3 Editing Unit Files (Overrides)

To avoid overwriting vendor-provided unit files, use overrides (drop-in files) instead of editing the original.

Step 1: Create an Override File

Run systemctl edit <service> to open a temporary editor for the service’s override:

systemctl edit nginx.service  

This creates a directory /etc/systemd/system/nginx.service.d/ and a file override.conf inside it.

Step 2: Add Custom Directives

For example, to make Nginx restart on failure and run as the nginx user:

[Service]  
User=nginx  
Group=nginx  
Restart=on-failure  
RestartSec=5  

Step 3: Apply Changes

After saving, reload systemd to apply the override:

systemctl daemon-reload  

Restart the service to activate the new configuration:

systemctl restart nginx  

5. Advanced Service Management

5.1 Masking vs. Disabling Services

  • Disable: Prevents the service from starting automatically on boot, but you can still start it manually with systemctl start <service>.

    systemctl disable nginx  
  • Mask: Completely blocks the service from starting (even manually). Systemd symlinks the unit file to /dev/null.

    systemctl mask nginx  

To unmask:

systemctl unmask nginx  

5.2 Timers: Schedule Tasks (Cron Alternatives)

Systemd timers (.timer units) schedule services to run at specific times, replacing cron for systemd-aware tasks.

Example: Daily Backup Timer

  1. Create a service unit to run the backup script (/usr/local/bin/backup.sh):

    sudo nano /etc/systemd/system/backup.service  

    Add:

    [Unit]  
    Description=Daily backup service  
    
    [Service]  
    Type=oneshot  # Run once and exit  
    ExecStart=/usr/local/bin/backup.sh  
    User=backup-user  
  2. Create a timer unit to schedule the service:

    sudo nano /etc/systemd/system/backup.timer  

    Add:

    [Unit]  
    Description=Run daily backup at 3 AM  
    
    [Timer]  
    OnCalendar=*-*-* 03:00:00  # Every day at 3:00 AM  
    Persistent=true  # Run missed tasks on boot (if the system was off at 3 AM)  
    
    [Install]  
    WantedBy=timers.target  # Enable when timers.target is active  
  3. Enable and start the timer:

    systemctl enable --now backup.timer  
  4. List active timers:

    systemctl list-timers --all  

5.3 Service Dependencies

Control the order in which services start with [Unit] directives:

  • Requires=<service>: The service must start; if it fails, this service also fails.
  • Wants=<service>: The service should start, but this service continues if it fails (weaker than Requires).
  • After=<service>: Start this service after the specified service (e.g., After=mysql.service for a web app needing MySQL).
  • Before=<service>: Start this service before the specified service.

Example: A Node.js app requiring PostgreSQL:

[Unit]  
Description=Node.js API Service  
After=network.target postgresql.service  
Requires=postgresql.service  # Fail if PostgreSQL doesn't start  

6. Troubleshooting Services

6.1 Check Logs with journalctl

Systemd’s journalctl command accesses logs from journald (the systemd logging daemon). Use it to debug service failures:

CommandPurpose
journalctl -u <service>Show logs for a specific service.
journalctl -u nginx -f”Follow” live logs for Nginx.
journalctl -u nginx --since "10min ago"Show logs from the last 10 minutes.
journalctl -u nginx -p errShow only error logs (priority err).
journalctl -bShow logs from the current boot.

6.2 Validate Unit Files

Check for syntax errors in unit files:

systemd-analyze verify nginx.service  

6.3 Debug Failed Services

If a service fails to start:

  1. Check status:

    systemctl status nginx  
  2. View logs:

    journalctl -u nginx -b  # Logs from current boot  
  3. Check dependencies:

    systemctl list-dependencies nginx.service  # List required services  
  4. Test the ExecStart command manually:
    Run the ExecStart command from the unit file in the terminal to see if it works (e.g., /usr/sbin/nginx -g "daemon on; master_process on;").

7. Conclusion

Systemd is a powerful tool for managing Linux services, offering flexibility, speed, and centralized control. By mastering systemctl, unit files, and advanced features like timers and dependencies, you can ensure your services run reliably and efficiently.

Start small: practice enabling/disabling services, check statuses with systemctl status, and experiment with overrides to customize behavior. Over time, you’ll leverage systemd’s full potential to automate tasks, troubleshoot issues, and optimize your system.

8. References