systemd in Everyday Use
- systemd is the first process every mainstream Linux distribution launches at boot and the parent of almost everything else.
- The main user-facing tool is
systemctlfor managing units (services, timers, sockets, targets). journalctlreads the logs systemd captures from those units.- You almost never need to write unit files by hand to use the system effectively; recognising them is enough.
What systemd actually is
systemd is the init system on every mainstream Linux distribution. After the kernel finishes booting, it hands control to systemd as process ID 1, and systemd is responsible for bringing up the rest of the system: mounting filesystems, configuring the network, starting daemons, opening a login prompt, and arranging the dependencies between all of those steps.
Beyond init, systemd is a suite of components for managing a running Linux system: a service manager, a logger, a network configuration daemon (where the distribution uses it), a login manager, a time synchronisation daemon and several other pieces. You don't have to use all of them; most distributions pick which components they ship and leave the rest off.
The design of systemd has been a source of long-running debate in the Linux community. That debate is not what this page is about. As a practical matter, if you run Ubuntu, Debian, Fedora, openSUSE, Arch, RHEL or any of the distributions derived from them, your machine boots with systemd, and the tools below are the ones you reach for to manage it.
Units: the building blocks
systemd models everything it manages as a unit. There are several kinds of unit, distinguished by file extension:
.service— a daemon or one-shot task. The most common type..timer— a schedule that triggers another unit (usually a service). The systemd equivalent of a cron job..socket— a socket that, when something connects, launches an associated service on demand..mount— a filesystem mount point..target— a group of other units. Targets play a role similar to traditional runlevels..path,.swap,.device,.slice,.scope— less commonly handled by users directly.
Unit definitions live in a few well-known places:
/usr/lib/systemd/system/— installed by packages. Do not edit these directly; they get overwritten on upgrade./etc/systemd/system/— local overrides. Files here take precedence and survive package upgrades.~/.config/systemd/user/— per-user units, managed withsystemctl --userrather than the system instance.
Everyday systemctl
The bulk of day-to-day systemd interaction goes through systemctl. The commands you'll use most often:
# See what's running and what's failed
systemctl list-units --type=service
systemctl --failed
# Inspect one specific service
systemctl status nginx.service
# Start, stop, restart, reload
sudo systemctl start nginx.service
sudo systemctl stop nginx.service
sudo systemctl restart nginx.service
sudo systemctl reload nginx.service
# Should this service start on boot?
sudo systemctl enable nginx.service
sudo systemctl disable nginx.service
# Combine enable + start (or disable + stop)
sudo systemctl enable --now nginx.service
sudo systemctl disable --now nginx.service
The distinction between enable and start trips people up: enable arranges for the service to start automatically at boot, but doesn't start it now. start launches it immediately but doesn't arrange for it to come back next time. Most of the time you want both — hence the --now shortcut.
systemctl status is also the right starting point when something has gone wrong. The output includes the unit's current state, when it was last started, the immediate parent process and the most recent log lines from the journal. For a service that won't start, those log lines often contain the answer.
Targets: replacing runlevels
Older init systems used numeric runlevels (3 for multi-user, 5 for graphical, and so on). systemd replaces these with named targets. A target is just a special kind of unit that pulls in other units; "reaching" a target means starting all of its dependencies.
The targets you might encounter on a desktop or server:
multi-user.target— the equivalent of old runlevel 3: text-mode multi-user system, no graphical login.graphical.target— adds a graphical login on top of multi-user. The default on desktop installs.rescue.target— single-user with minimal services. Useful for recovery.emergency.target— only a root shell with a read-only root filesystem. Used when even rescue can't come up cleanly.reboot.target,poweroff.target,halt.target— exactly what they sound like.
# What's the current default target?
systemctl get-default
# Switch to it right now (without rebooting)
sudo systemctl isolate multi-user.target
# Make a different target the default for next boot
sudo systemctl set-default multi-user.target
You can also enter rescue or emergency mode at boot by editing the GRUB kernel line and appending systemd.unit=rescue.target or systemd.unit=emergency.target. This is the modern equivalent of "boot to single-user mode".
journalctl: reading the logs
The systemd journal captures structured log output from every unit, as well as kernel messages and anything written to /dev/log. It is read with journalctl.
# Most recent entries, like tail -f
journalctl -f
# Only this boot
journalctl -b
# Only the previous boot (useful for crash investigation)
journalctl -b -1
# Only one unit's logs
journalctl -u sshd.service
# Only kernel messages
journalctl -k
# Only errors and above
journalctl -p err -b
# Logs since a specific time
journalctl --since "2026-05-01 09:00" --until "2026-05-01 18:00"
On most distributions the journal is configured to persist across reboots; on a few it is volatile by default. If journalctl -b -1 returns nothing, journal persistence is probably off; the systemd documentation describes how to switch it on by creating /var/log/journal/.
For ad-hoc shell sessions that aren't connected to a service, journalctl's --user mode reads logs from per-user services started with systemctl --user.
Timers: the modern cron
systemd timers are the systemd-native equivalent of cron jobs. A timer unit triggers a service unit on a schedule. Compared to cron, timers integrate with the journal (so you can see why a missed job missed), can be tied to system boot or login events, and can attach resource limits to the triggered service.
To see the timers currently configured on a system:
systemctl list-timers --all
Each row shows the timer's next trigger, the last time it fired, and the service it activates. For routine system maintenance — log rotation, package-cache cleanup, ClamAV signature updates — most distributions now use timers instead of /etc/cron.daily/. The rsync home backup and SSL certificate expiry checker scripts both include ready-to-use timer unit examples.
Overriding a unit without editing it
Distributions occasionally ship unit files that aren't quite what you want — maybe you need a service to run as a different user, or you want to tighten its sandboxing. The right way to handle this is with a drop-in, not by editing the original file. Drop-ins survive package upgrades; edits to the original do not.
# Create a drop-in (this opens an editor and creates the right directory)
sudo systemctl edit nginx.service
The drop-in goes in /etc/systemd/system/<unit>.d/override.conf and only contains the lines you want to change. After saving, run sudo systemctl daemon-reload and restart the service.
Common mistakes
- Editing files in
/usr/lib/systemd/system/. They will be overwritten the next time the package is upgraded. Usesystemctl editor copy the file into/etc/systemd/system/before editing. - Forgetting
daemon-reloadafter changing a unit file. systemd caches loaded unit files; if you don't reload, your changes are ignored. - Confusing
enablewithstart. See above. - Trying to manage a user service with
sudo systemctl. Per-user services needsystemctl --user(without sudo). Mixing them up produces confusing error messages. - Trying to read systemd's own logs with
tail -f /var/log/messages. On a pure systemd install, those files may not exist or may not be complete.journalctlis the canonical interface.
Related reading
- Linux troubleshooting — including how to use
systemctl statusandjournalctlin a diagnostic loop. - Essential Linux commands — the broader command-line reference.
- Linux security overview — including kernel updates, where a reboot brings the new code into play after a systemd-managed update.
- The Linux kernel — the layer underneath systemd.