Services with systemd & systemctl
A service (also called a daemon) is a program that runs in the background without a terminal: the web server, the database, the SSH server, the firewall. Something has to start these at boot, restart them if they crash, and let administrators control them. On Ubuntu and nearly every modern distribution, that something is systemd, and you talk to it with the systemctl command.
In this lesson you will check, start, stop and enable services, understand what systemctl status tells you, and write a unit file for your own app.
systemd and units
systemd is the first process the kernel starts (PID 1). It starts everything else and keeps track of it all. Ubuntu 26.04 ships systemd 259. systemd manages units, each described by a small text file. The kinds you will meet most are:
.service: a program to run, such asnginx.serviceorssh.service.timer: a schedule that starts a service (see Scheduling: cron & systemd Timers).target: a group of units representing a system state, such asmulti-user.target(a normal server, no desktop).socketand.mount: network sockets and mounted filesystems
Unit files from packages live in /usr/lib/systemd/system/. Your own units and changes go in /etc/systemd/system/, which takes priority and is never overwritten by package updates.
Checking a service
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 Fri 2026-10-30 08:01:14 IST; 2h 41min ago
Docs: man:nginx(8)
Main PID: 845 (nginx)
Tasks: 3 (limit: 4558)
Memory: 4.2M (peak: 6.1M)
CPU: 41ms
CGroup: /system.slice/nginx.service
├─845 "nginx: master process /usr/sbin/nginx -g daemon on; master_process on;"
├─846 "nginx: worker process"
└─847 "nginx: worker process"
Oct 30 08:01:14 shop-server systemd[1]: Starting nginx.service - A high performance web server and a reverse proxy server...
Oct 30 08:01:14 shop-server systemd[1]: Started nginx.service - A high performance web server and a reverse proxy server.Read it from the top. The green dot means healthy (a red one means failed). Loaded shows the unit file and two important words: enabled (it starts at boot) and the vendor preset. Active: active (running) and the time since it started tell you it is up. Main PID and the CGroup tree list its processes. The last lines are the most recent log messages for this service, which is often where you find why something failed. Press q if the output opens in a pager.
You can use the name with or without .service. For scripts, two quiet checks are handy: systemctl is-active nginx prints active or inactive, and systemctl is-enabled nginx prints enabled or disabled.
Starting, stopping and enabling
Two separate questions apply to every service: is it running now? and will it start at boot?
| Command | Effect |
|---|---|
sudo systemctl start nginx | Start it now |
sudo systemctl stop nginx | Stop it now |
sudo systemctl restart nginx | Stop and start again (short downtime) |
sudo systemctl reload nginx | Re-read config without stopping, if the service supports it |
sudo systemctl enable nginx | Start automatically at every boot |
sudo systemctl disable nginx | Do not start at boot |
sudo systemctl enable --now nginx | Enable and start in one step |
sudo systemctl mask nginx | Block it from being started at all, even by other units |
sudo systemctl enable --now nginx
sudo nginx -t && sudo systemctl reload nginxSynchronizing state of nginx.service with SysV service script with /usr/lib/systemd/systemd-sysv-install. Executing: /usr/lib/systemd/systemd-sysv-install enable nginx nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
The second line is a habit worth copying: test the configuration first (nginx -t), and reload only if the test passes. A broken config plus restart means your website goes down; a broken config caught by the test means nothing changes.
Listing services and finding failures
systemctl list-units --type=service --state=running
systemctl --failedUNIT LOAD ACTIVE SUB DESCRIPTION cron.service loaded active running Regular background program processing daemon nginx.service loaded active running A high performance web server and a reverse proxy server ssh.service loaded active running OpenBSD Secure Shell server systemd-journald.service loaded active running Journal Service ... UNIT LOAD ACTIVE SUB DESCRIPTION ● sweets-api.service loaded failed failed Sharma Sweets order API
systemctl --failed is the first thing to run after a reboot that "did not come back right". To see why a service failed, read its log with journalctl -u sweets-api, explained fully in Logs & journalctl.
Writing your own service
Suppose Priya has a small Python API in /opt/sweets-api. Running it in a terminal stops when she logs out. A unit file makes systemd run it as a proper service: started at boot, restarted on crash, logged to the journal. Create /etc/systemd/system/sweets-api.service:
[Unit]
Description=Sharma Sweets order API
After=network-online.target
Wants=network-online.target
[Service]
User=sweets
WorkingDirectory=/opt/sweets-api
Environment=APP_ENV=production
ExecStart=/opt/sweets-api/.venv/bin/python app.py
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target[Unit] describes the service and its ordering: start after the network is up. [Service] says how to run it: as the unprivileged user sweets, from which folder, with which command (always a full path), and to restart it five seconds after a crash. [Install] says which target pulls it in when you enable it. Then tell systemd about the new file and start it:
sudo systemctl daemon-reload
sudo systemctl enable --now sweets-api
systemctl status sweets-api --no-pager● sweets-api.service - Sharma Sweets order API
Loaded: loaded (/etc/systemd/system/sweets-api.service; enabled; preset: enabled)
Active: active (running) since Fri 2026-10-30 11:05:42 IST; 3s ago
Main PID: 3391 (python)
...Run daemon-reload after every change to a unit file; otherwise systemd keeps using the old version.
Power and targets
systemctl also controls the machine itself: sudo systemctl reboot restarts and sudo systemctl poweroff shuts down (sudo reboot and sudo shutdown -h now do the same). systemctl get-default shows the target the system boots into: graphical.target on desktops, multi-user.target on servers.
Common mistakes
- Starting but not enabling. The service runs today and is missing after the next reboot. Use
enable --now. - Forgetting
daemon-reload. systemd warns that the unit file changed on disk and keeps the old settings. - Relative paths in
ExecStart. systemd does not use yourPATHor current folder; write full paths. - Running your app as root. Create a dedicated user and set
User=, so a bug in the app cannot take over the server. - Restarting with a broken config. Test first (
nginx -t,apachectl configtest,sshd -t).
Key points
- systemd (PID 1) manages services and other units;
systemctlcontrols it. systemctl statusshows whether a service is enabled, running, its PIDs and recent log lines.start/stop/restart/reloadact now;enable/disabledecide what happens at boot;enable --nowdoes both.- Your own unit files go in
/etc/systemd/system/; rundaemon-reloadafter editing them. - Use
systemctl --failedandjournalctl -u nameto troubleshoot.
Exercise
Write a systemd service called backup-notes.service that runs the command /usr/bin/tar -czf /home/priya/notes-backup.tar.gz -C /home/priya notes once as user priya. Use Type=oneshot, which means "run the command and finish" instead of staying running. Then load it, run it once, and check whether it succeeded.
Show solution
Create /etc/systemd/system/backup-notes.service:
[Unit]
Description=Back up Priya's notes folder
[Service]
Type=oneshot
User=priya
ExecStart=/usr/bin/tar -czf /home/priya/notes-backup.tar.gz -C /home/priya notessudo systemctl daemon-reload
sudo systemctl start backup-notes
systemctl status backup-notes --no-pager○ backup-notes.service - Back up Priya's notes folder
Loaded: loaded (/etc/systemd/system/backup-notes.service; static)
Active: inactive (dead)
...
Oct 30 11:20:03 laptop systemd[1]: Finished backup-notes.service - Back up Priya's notes folder.A oneshot service shows inactive (dead) after it finishes, and the log line "Finished" confirms success. It has no [Install] section, so it is static: it runs only when started by hand or by a timer, which you will add in the scheduling lesson.
Quick Quiz
1. Which command makes a service start automatically at boot?
enable creates the links that start it at boot; start only runs it now.
2. You edited /etc/systemd/system/app.service. What must you run before restarting the service?
daemon-reload makes systemd re-read changed unit files.
3. Where should your own unit files go?
/etc/systemd/system is for administrator files and overrides; package files live in /usr/lib.
4. What is the safest way to apply a changed nginx config?
Testing first prevents a broken config from taking the site down; reload avoids downtime.
Learn Linux with a mentor
Free lessons get you started. Our Ethical Hacking & Cyber Security training adds real projects and code reviews from working developers.
- Project-based learning
- Mentor code reviews
- Free counselling call
