systemd — Service Management, Units, and Targets

LINUX-SYSTEMD

How systemd manages the Linux system from boot to shutdown — organising daemons and resources as units with declarative configuration files, controlling services with systemctl, and using targets as dependency-based milestones that replace traditional SysV runlevels.

linuxsystemdservicesunitstargets

Overview

systemd is PID 1 on RHEL 9. It is the first userspace process started by the kernel at boot, and it is responsible for initialising the system, starting and managing services throughout the system’s operational life, and coordinating the shutdown sequence. It replaces the traditional SysV init system and Upstart that were used on older RHEL versions.

The core advantage of systemd over SysV init is parallel service startup. SysV init started services sequentially using numbered shell scripts in /etc/rc.d/ — each service had to complete before the next could begin. systemd tracks dependencies between services and starts independent services simultaneously, dramatically reducing boot time on modern systems with multiple CPU cores.

Beyond faster boot, systemd provides socket activation (services started on-demand when a connection arrives on their socket), D-Bus activation, on-demand mounting of filesystems, and tight integration with cgroups (control groups) for resource accounting and limiting. All logs produced by systemd-managed services are captured by systemd-journald, which stores them in a structured binary format queryable with journalctl.


Units

systemd organises everything it manages as a unit. A unit is a configuration file that describes a resource, service, or relationship. Units are identified by their filename, which ends in a suffix indicating the unit type.

Unit TypeSuffixPurpose
Service.serviceA daemon process or one-shot command
Socket.socketA network or IPC socket; activates a service when traffic arrives
Path.pathA filesystem path watcher; activates a service when path changes
Timer.timerA cron-like scheduled trigger for activating another unit
Target.targetA synchronisation point grouping other units — analogous to a runlevel
Mount.mountA filesystem mount point
Device.deviceA kernel device, auto-created from udev data
Slice.sliceA cgroup hierarchy node for resource control

When you refer to a unit without a suffix, systemd assumes .service. So systemctl start nginx and systemctl start nginx.service are equivalent.


Unit File Locations

Unit files exist in three locations with a defined precedence order (highest to lowest):

LocationPrecedencePurpose
/etc/systemd/system/HighestAdministrator customisations; overrides vendor defaults
/run/systemd/system/MiddleRuntime-generated units; temporary, cleared at reboot
/usr/lib/systemd/system/LowestVendor and package-provided defaults; do not edit directly

When a package installs a service (for example, nginx or sshd), its unit file goes into /usr/lib/systemd/system/. To customise a vendor unit without modifying the original, create an override in /etc/systemd/system/ — either a complete replacement or a drop-in directory (/etc/systemd/system/nginx.service.d/override.conf) containing only the settings you want to change.


Controlling Services with systemctl

The systemctl command is the primary interface for managing units:

CommandEffect
systemctl start unitStart the unit immediately
systemctl stop unitStop the unit
systemctl restart unitStop then start (full restart)
systemctl reload unitAsk the unit to reload its configuration without restarting
systemctl enable unitCreate a symlink so the unit starts at boot
systemctl disable unitRemove the symlink; unit will not start at boot
systemctl status unitShow current state, recent log lines, and PID
systemctl is-active unitExit code 0 if active; useful in scripts
systemctl is-enabled unitExit code 0 if enabled for boot
systemctl mask unitSymlink to /dev/null — prevents any attempt to start
systemctl unmask unitReverse a mask
systemctl daemon-reloadReload all unit files from disk
systemctl list-unitsShow all currently loaded and active units
systemctl list-unit-filesShow all units and their enabled state

Enabling a unit makes it start automatically at boot by creating a symbolic link in the appropriate .wants/ or .requires/ directory of the default target. It does not start the unit immediately. Use systemctl enable --now unit to enable and start in one step.

Masking is stronger than disabling. A masked unit cannot be started manually or as a dependency. It is used when you want to guarantee that a unit never runs — for example, masking firewalld.service if a different firewall tool is deployed.

systemctl daemon-reload must be run after creating or modifying unit files in /etc/systemd/system/. Without it, systemd continues using the version of the unit it loaded at startup and ignores your changes.


Service Unit File Structure

A .service unit file has three sections:

[Unit]
Description=My Application Server
Documentation=https://example.com/docs
After=network.target
Requires=postgresql.service
Wants=redis.service

[Service]
Type=simple
User=appuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/server --config /etc/myapp/config.toml
ExecStop=/opt/myapp/bin/server --stop
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

[Unit] section — metadata and dependency declarations:

[Service] section — how the process runs:

[Install] section — where to hook this unit when enabled:


Targets

A target is a synchronisation point that groups related units. When systemd activates a target, it activates all units that the target requires or wants. Targets replaced SysV runlevels.

TargetEquivalent RunlevelDescription
emergency.targetMinimal root shell, no filesystems mounted
rescue.target1Single-user maintenance mode
multi-user.target3Non-graphical multi-user system
graphical.target5Multi-user with graphical display manager
reboot.target6Reboot the system
poweroff.target0Halt and power off
systemctl get-default                    # Show the default target (boots into this)
systemctl set-default graphical.target   # Change default target
systemctl isolate rescue.target          # Switch to target immediately (like changing runlevel)
systemctl isolate multi-user.target      # Drop to text mode without rebooting

systemctl isolate activates the specified target and stops all units not required by it. This allows switching between graphical and text modes on a live system, or entering rescue mode without a reboot.


Practical Workflow

A typical workflow for deploying a custom service unit:

  1. Create the unit file at /etc/systemd/system/myapp.service
  2. Run systemctl daemon-reload to make systemd aware of the new file
  3. Run systemctl start myapp to test it
  4. Check systemctl status myapp and journalctl -u myapp -f for errors
  5. Run systemctl enable myapp to make it persistent across reboots
  6. Verify with systemctl is-enabled myapp

Summary

systemd is PID 1 on RHEL 9 and manages all system resources through a unit file model. Service units define how daemons run; socket and timer units enable on-demand and scheduled activation; target units group units into dependency-based boot milestones that replace SysV runlevels. The systemctl command is the single interface for starting, stopping, enabling, disabling, and inspecting all units. Always run systemctl daemon-reload after modifying unit files in /etc/systemd/system/ — without it, systemd will silently continue using the old configuration.