Module 6 · 6.1
English
Managing services with systemd
Module 6: Services and logs · Reading time: 10 minutes
Learning objective: After this lesson you can start, stop and reload services and have them start at boot, read the status of a service, and safely change a service setting with a drop-in.
Key concepts: systemd, unit, service, systemctl, start, stop, restart, reload, enable, disable, --now, active, inactive, failed, systemctl --failed, drop-in, systemctl edit, daemon-reload, Restart=
Who keeps everything running?
A server runs dozens of programs that always need to be there: the SSH server, the web server, a database, time synchronisation. Programs like these are called services (or daemons). Something has to start them at boot, keep an eye on them and restart them if they fall over. On Debian, Ubuntu, AlmaLinux and Rocky Linux, systemd does that. It is the first program the kernel starts (process 1), and it then starts everything else.
systemd works with units: descriptions of something it has to manage. The most important types:
| Type | Extension | Example |
|---|---|---|
| Service | .service | nginx.service, ssh.service |
| Timer (scheduled task) | .timer | apt-daily.timer (lesson 4.2, lesson 6.3) |
| Socket | .socket | ssh.socket on Ubuntu 24.04 and later |
| Target (group of units) | .target | multi-user.target |
You talk to systemd with the systemctl command. You can leave out the .service extension: systemctl status nginx is the same as systemctl status nginx.service.
Reading the status
The command you will use most often:
anna@web1:~$ systemctl status nginx
● nginx.service - A high performance web server and a reverse proxy server
Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: enabled)
Active: active (running) since Mon 2026-11-09 08:12:44 CET; 3h 2min ago
Docs: man:nginx(8)
Process: 902 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 905 (nginx)
Tasks: 3 (limit: 2275)
Memory: 4.1M (peak: 6.3M)
CPU: 213ms
CGroup: /system.slice/nginx.service
├─905 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
└─906 "nginx: worker process"
nov 09 08:12:44 web1 systemd[1]: Starting nginx.service - A high performance web server...
nov 09 08:12:44 web1 systemd[1]: Started nginx.service - A high performance web server...Read it from top to bottom:
- The dot in front of the name is green for a running service, white for a stopped one and red for a failed one.
- Loaded tells you where the unit file is and whether the service starts at boot (
enabled) or not (disabled). - Active tells you whether it is running now (
active (running)), has stopped (inactive (dead)) or has failed (failed), and since when. - Main PID and CGroup show which processes belong to the service.
- At the bottom you see the last lines from the service's log. They often already tell you why something is going wrong; you can read more with
journalctl(lesson 6.2).
Starting, stopping, restarting and reloading
anna@web1:~$ sudo systemctl start nginx # start now
anna@web1:~$ sudo systemctl stop nginx # stop now
anna@web1:~$ sudo systemctl restart nginx # stop and start again
anna@web1:~$ sudo systemctl reload nginx # reload config without stoppingThe difference between restart and reload matters in practice. With a restart the service stops briefly: open connections are dropped, and if the new configuration contains an error, it won't start again and your website is down. With a reload the service rereads its configuration while it keeps running; if the configuration has an error, nginx keeps the old one. So after a configuration change to nginx, Caddy, SSH or fail2ban, use reload, and test the configuration first (nginx -t, sshd -t, fail2ban-client -t). Not every service supports reload; systemctl reload-or-restart picks for you.
At boot: enable and disable
Starting and "starting at boot" are two different things:
anna@web1:~$ sudo systemctl enable nginx # start at boot from now on
anna@web1:~$ sudo systemctl disable nginx # no longer at boot
anna@web1:~$ sudo systemctl enable --now nginx # both: start now and at boot
anna@web1:~$ systemctl is-enabled nginx
enabledA classic mistake: you start a service with start, everything works, and after the next reboot (for example after a kernel update, lesson 4.2) it's gone. So for a new service, use enable --now.
If you want to be sure a service never starts, not even when another service asks for it, there is mask: sudo systemctl mask <dienst>. Undo it with unmask.
What's wrong?
One command shows all failed units:
anna@web1:~$ systemctl --failed
UNIT LOAD ACTIVE SUB DESCRIPTION
● php8.4-fpm.service loaded failed failed The PHP 8.4 FastCGI Process Manager
1 loaded units listed.Make this a habit, for example after every reboot and every upgrade (lesson 4.3): the list should be empty. Once you have fixed the problem, clear the entry with sudo systemctl reset-failed.
An overview of all running services:
anna@web1:~$ systemctl list-units --type=service --state=runningIf something is running that you don't recognise or don't use, find out what it is. Every service you don't need is unnecessary attack surface (lessons 5.1 and 10.1).
Unit files and drop-ins
A unit file is a text file. The package's version is in /usr/lib/systemd/system/ (on older systems /lib/systemd/system/). You never edit that one: a package update overwrites it. Put your own changes in a drop-in: a small file containing only the lines you want to change. The easiest way is:
anna@web1:~$ sudo systemctl edit nginxAn editor opens with an empty section between two comment lines. Whatever you write there ends up in /etc/systemd/system/nginx.service.d/override.conf. For example: restart nginx automatically if it stops unexpectedly.
[Service]
Restart=on-failure
RestartSec=5sWhen you save, systemctl edit reloads the systemd configuration automatically. If you edit a unit file some other way, run this yourself:
anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl restart nginxdaemon-reload makes systemd reread the unit files; the service itself still needs a restart to use the change. You can see the full result (original plus drop-ins) with systemctl cat nginx.
Restart=on-failure is a good habit for important services. But don't use it to hide a real fault: a service that crashes and restarts every five seconds needs looking up in the log. After a few quick failures in a row, systemd stops restarting (the default limit is five starts within ten seconds) and marks the service as failed.
On AlmaLinux and Rocky Linux
systemd and systemctl work exactly the same. Only the service names sometimes differ: the SSH service is called sshd, the distribution's web server is httpd (Apache) or nginx, and the firewall is firewalld.
In practice
Your provider's VPS screen (at WebOké and elsewhere) can shut down the whole server, restart it or "force it off". That last option is pulling the plug: services get no chance to stop cleanly and a database can get damaged. Inside the server, use sudo systemctl reboot or sudo shutdown -h now, and in the panel use the normal shut down or restart button.
Summary
- systemd starts and monitors all services; you control it with
systemctl. systemctl statusshows whether a service is running, whether it starts at boot, and the last log lines.start/stop/restartapply to right now,enable/disableto boot; useenable --nowfor a new service.- After a configuration change: test first, then
reload;systemctl --failedshould be empty. - Never edit a package's unit file; use a drop-in with
systemctl editinstead.
Quiz
Exercise
Exercise O6.1: Mapping your services. On your server, make a list of all running services (systemctl list-units --type=service --state=running) and check whether systemctl --failed is empty. For each service, note what it does and whether you need it. Pick one service you didn't know and find out what it is (systemctl status, man). Then set Restart=on-failure in a drop-in for one important service and check with systemctl cat that it is there.
Exercise O6.1: Mapping your services
You do this exercise yourself; no one checks it. Tick off what you've done and mark the exercise as done.
A drop-in lives in /etc/systemd/system/<naam>.service.d/override.conf, not in /usr/lib/systemd. With reload the service keeps running, and nginx, for example, keeps the old configuration if there is an error; test first with nginx -t or sshd -t. Unneeded services: disable --now or remove the package.
Your ticks and notes only stay in this browser; we don't send them anywhere. If you're signed in, we only save in My courses that you've done the exercise.
Further reading
- Manual
systemctl(1): https://manpages.debian.org/trixie/systemd/systemctl.1.en.html - Manual
systemd.service(5)(Restart=): https://manpages.debian.org/trixie/systemd/systemd.service.5.en.html - Manual
systemd.unit(5)(drop-ins): https://manpages.debian.org/trixie/systemd/systemd.unit.5.en.html
