Managing Services with systemd
Most of the software that runs on a server never shows you a window or a prompt. A web server, a database, an SSH server (the program that lets you log in remotely) all run quietly in the background, starting up when the machine boots and staying alive for weeks at a time. On Ubuntu, the program in charge of starting, stopping, and watching over all of these background programs is systemd. Learning to drive systemd is one of the first real skills of Linux server administration, because almost everything you install becomes a service that systemd manages.
What is systemd and what is a service?
systemd is the init system on Ubuntu. An init system is the very first program the kernel starts when the machine boots (it always has process ID 1), and its job is to launch and supervise every other background program. It has been the default on Ubuntu since version 15.04, and it runs on Ubuntu 22.04 and 24.04 LTS today.
A daemon is a long-running background program (the name is an old Unix term, pronounced “demon”). When systemd manages a daemon, it does so through a unit — a small text file that tells systemd how to run the program. The most common kind of unit is a service unit, whose filename ends in .service. For example, the Nginx web server is managed by a unit called nginx.service.
You control units with one command: systemctl (short for “system control”).
Almost every
systemctlcommand that changes something needssudo(administrator rights), because starting and stopping services affects the whole machine. Read-only commands likestatusandlist-unitsdo not.
The core commands
Let’s install Nginx (a popular web server and reverse proxy — a server that sits in front of your app and forwards web requests to it) so we have a real service to manage.
sudo apt update
sudo apt install -y nginx
On Ubuntu, installing a service usually starts it and enables it automatically. Here are the five commands you will use every single day, using nginx as the example. The .service suffix is optional — systemctl start nginx and systemctl start nginx.service mean the same thing.
| Command | What it does | When to use it |
|---|---|---|
sudo systemctl start nginx | Starts the service right now | Bring a stopped service back to life |
sudo systemctl stop nginx | Stops the service right now | Take a service offline for maintenance |
sudo systemctl restart nginx | Stops then starts it | Apply a config change that needs a full restart |
sudo systemctl reload nginx | Re-reads config without dropping connections | Apply config changes gracefully (Nginx supports this) |
systemctl status nginx | Shows whether it is running and recent logs | Check health and debug problems |
Prefer reload over restart when the service supports it, because reload applies new settings without dropping active connections. Use restart when a setting only takes effect on a full restart.
Reading the status output
systemctl status is the command you will run most often. It tells you at a glance whether a service is healthy.
systemctl status nginx
Output:
● 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-06-15 09:14:02 UTC; 2h 31min ago
Docs: man:nginx(8)
Process: 812 ExecStartPre=/usr/sbin/nginx -t -q -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Process: 815 ExecStart=/usr/sbin/nginx -g daemon on; master_process on; (code=exited, status=0/SUCCESS)
Main PID: 816 (nginx)
Tasks: 3 (limit: 4613)
Memory: 6.2M
CPU: 84ms
CGroup: /system.slice/nginx.service
├─816 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
└─817 "nginx: worker process"
Here is what the important lines mean:
- The colored dot at the top: green means running, white means stopped, red means it crashed.
- Loaded: confirms the unit file was found, and shows
enabledordisabled(boot behavior, explained next). - Active: the single most important line.
active (running)is healthy.inactive (dead)means it is stopped.failedmeans it crashed — investigate immediately. - Main PID: the process ID, which you can use with other tools.
- The last few lines are recent log messages, handy for spotting errors.
Enable vs start — the difference that trips everyone up
This is the concept beginners miss most often, so let’s be precise.
startruns the service now, in this current session. If you reboot the machine, the service will not come back unless something else starts it.enabledoes not start the service now. It tells systemd “start this automatically every time the machine boots.” It works by creating a symbolic link (a shortcut) so the service is part of the boot sequence.
| Command | Starts it now? | Survives a reboot? |
|---|---|---|
sudo systemctl start nginx | Yes | No |
sudo systemctl enable nginx | No | Yes |
sudo systemctl enable --now nginx | Yes | Yes |
sudo systemctl disable nginx | No (leaves it running) | No |
In practice you almost always want both: start it now and make it boot-persistent. The shortcut --now does both in one command:
sudo systemctl enable --now nginx
Output:
Synchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
To check whether a service is set to start at boot:
systemctl is-enabled nginx
Output:
enabled
Forgetting to
enablea service is a classic production outage. Everything works fine until the server reboots months later — and the database or web server simply never comes back. Whenever you set up a service you depend on, runsystemctl is-enabledto confirm it will survive a reboot.
Listing and finding services
To see every active service on the machine:
systemctl list-units --type=service
To see only the ones that failed (a great first stop when something is broken):
systemctl --failed
Output:
UNIT LOAD ACTIVE SUB DESCRIPTION
● certbot.service loaded failed failed Certbot renewal
LOAD = Reflects whether the unit definition was properly loaded.
ACTIVE = The high-level unit activation state.
SUB = The low-level unit activation state.
1 loaded units listed.
If a service refuses to start, the status output points you at the logs. You can read the full log for any unit with journalctl (covered in detail in the logging page):
journalctl -u nginx --since "1 hour ago"
Best Practices
- Use
systemctl enable --now <service>for anything that must come back after a reboot, then confirm withsystemctl is-enabled. - Prefer
reloadoverrestartfor services like Nginx so you don’t drop live connections. - Before restarting Nginx, validate the config first with
sudo nginx -t— a broken config will refuse to reload, saving you from downtime. - Make
systemctl statusandsystemctl --failedyour first move when debugging; they tell you state and recent errors in one place. - Always type the full unit name when unsure, and use Tab completion —
systemctl status ngi<Tab>saves typos. - Never edit unit files under
/usr/lib/systemd/system/directly; those are overwritten by package updates. Use overrides under/etc/systemd/system/instead. - After changing any unit file, run
sudo systemctl daemon-reloadso systemd picks up the changes.