systemd is the init and service management system on Linux that displaced the traditional init in the 2010s. Its key feature is starting services in parallel during boot, so the system starts noticeably faster.
All the examples below revolve around a single service myapp — how to create
your own is shown in the "Creating a service" section.
Basic concepts#
- Unit — the base management unit of systemd: a configuration file describing a resource (a service, socket, device, mount point)
- Service — a unit type for daemons and processes (
*.service) - Target — a group of units activated together; the successor of the runlevel of traditional init
- cgroup (control group) — a kernel mechanism: it groups processes for accounting and resource limits; systemd uses cgroups to track the processes of each service
The runlevel-to-target mapping:
| Runlevel | Target | What it is |
|---|---|---|
| 0 | poweroff.target | shutdown |
| 1 | rescue.target | single-user mode (recovery) |
| 3 | multi-user.target | multi-user without graphics (servers) |
| 5 | graphical.target | multi-user with graphics |
| 6 | reboot.target | reboot |
Managing a service#
# Start
systemctl start myapp
# Stop
systemctl stop myapp
# Restart (stop + start)
systemctl restart myapp
# Reload the service config without a restart
systemctl reload myapp
# Check the status: state, process tree, fresh log lines
systemctl status myapp
The
.servicesuffix is optional:systemctl start myappandsystemctl start myapp.serviceare the same thing. This article omits it.
Startup#
# Enable autostart and start the service right away
systemctl enable --now myapp
# Enable autostart only
systemctl enable myapp
# Remove from autostart
systemctl disable myapp
# Block completely (mask: it won't start even manually)
systemctl mask myapp
# Undo
systemctl unmask myapp
enabledoes not start the service itself — it starts on the next boot. To enable autostart and bring the service up right away —enable --now.
Creating a service#
The unit file goes into /etc/systemd/system/ — here it is myapp.service:
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=myuser
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/bin/myapp
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
Choosing Type= for the process behaviour:
| Type | When to use |
|---|---|
| simple | the process runs in the foreground and does not daemonize itself (the default) |
| forking | the process backgrounds itself in the classic Unix-daemon style |
| oneshot | a one-off task: runs and exits |
| notify | like simple, but the process reports readiness itself via sd_notify |
Restart=on-failure restarts the service only on crash; always — also
after a normal exit.
Accepted into service:
# Re-read units after changing files
sudo systemctl daemon-reload
# Enable autostart and start
sudo systemctl enable --now myapp
Working with targets#
# List available targets
systemctl list-units --type=target
# A target's dependency tree
systemctl list-dependencies graphical.target
# Switch the current session to no-graphics mode
sudo systemctl isolate multi-user.target
isolatestops everything that is not in the target target and its dependencies — including running graphical applications when leavinggraphical.target.
The default target for future boots:
# Which target will be activated at boot
systemctl get-default
# Make the graphical mode the default
sudo systemctl set-default graphical.target
Reboot and shutdown#
# Reboot the system
systemctl reboot
# Shut down
systemctl poweroff
Both commands are thin wrappers over the corresponding targets
(reboot.target, poweroff.target).
Service logs (journalctl)#
# All service logs
journalctl -u myapp
# Since the last system boot
journalctl -u myapp -b
# The last 100 lines, without a pager
journalctl -u myapp -n 100 --no-pager
# In real time
journalctl -u myapp -f
# Over a time interval
journalctl -u myapp --since "2026-06-30 10:00" --until "2026-06-30 12:00"
For existing services it is handy to view their unit with drop-ins:
systemctl cat myapp, and edit it withsudo systemctl edit myapp.