CoursesLinux essentialsProcesses & services

systemd units & timers

Start, enable, and inspect services.

Beginner14 min · lesson 21 of 25

systemd is the init system on modern Linux — PID 1 — and it manages services (called units): starting them, keeping them running, ordering their startup, and restarting them on failure. You interact with it through systemctl, and the same handful of verbs works for every service on the system. Learning systemctl is learning how to run, stop, and inspect essentially any daemon on a Linux host, from nginx to your own app.

terminal
$ systemctl status nginx # is it running? recent logs, PID, memory
$ systemctl start nginx # start it now
$ systemctl stop nginx # stop it now
$ systemctl restart nginx # stop then start
$ systemctl enable nginx # start automatically at boot
$ systemctl enable --now nginx # enable AND start in one step

start vs enable

A distinction that trips up beginners: start affects the service right now, while enable affects whether it starts automatically at boot — they are independent. A service can be running now but not enabled (it will not come back after a reboot), or enabled but currently stopped. When you deploy something that must survive reboots, you enable --now it. Checking systemctl is-enabled and is-active answers "will it start on boot?" and "is it up right now?" separately.

Unit files and timers

Each service is defined by a unit file (in /etc/systemd/system/ for your own, /lib/systemd/system/ for packaged ones) — a small text file declaring what to run, as which user, and when. Editing it and running systemctl daemon-reload applies changes. systemd also replaces cron for scheduled jobs with timer units, which are more powerful and logged through the journal. Running your own app as a systemd service (with a dedicated user, restart-on-failure, and resource limits) is the standard, secure way to keep it alive.

/etc/systemd/system/myapp.service
[Unit]
Description=My App
After=network.target
[Service]
User=appuser # run as a dedicated non-root user (security!)
ExecStart=/usr/local/bin/myapp
Restart=on-failure # systemd restarts it if it crashes
NoNewPrivileges=true # cannot gain privileges — a free hardening win
[Install]
WantedBy=multi-user.target # start at boot
Run services as their own user, not root
The default temptation is to run your app as root because "it just works" — but a systemd unit lets you set User= to a dedicated unprivileged account, plus hardening directives like NoNewPrivileges, ProtectSystem, and PrivateTmp for almost free. A service confined this way is far less dangerous if compromised. The unit file is where a lot of cheap per-service hardening lives; the server-hardening course goes deep on it.