systemd Units & Services

systemd Units

Once the kernel finishes booting, it hands off to PID 1 - on nearly every modern distro, that's systemd. Its job is to bring the rest of the system up: mounting remaining filesystems, starting background services, and managing everything that keeps running for as long as the machine is on.

systemd organizes everything it manages into units. A unit is a single named thing systemd knows how to start, stop, and track - the most common type is .service (a background daemon like nginx or sshd), but there are others: .socket (a network/IPC endpoint that can start a service on first connection), .target (a named grouping of other units, covered in the next section), .mount (a filesystem mount), .timer (a scheduled trigger, systemd's alternative to cron).

CommandAction
systemctl start nginxStart now
systemctl stop nginxStop now
systemctl restart nginxRestart
systemctl reload nginxReload config (no downtime)
systemctl enable nginxStart at boot
systemctl disable nginxDon't start at boot
systemctl enable --now nginxEnable and start
systemctl status nginxCurrent state
systemctl is-active nginxactive/inactive
systemctl list-units --type=serviceAll services

restart and reload look similar but behave very differently in practice: restart fully stops the process and starts a new one - briefly dropping any live connections - while reload sends the running process a signal asking it to re-read its configuration without stopping, if the service supports it (many web servers and databases do). Prefer reload when you only changed config and want zero downtime.

Unit definition files live in /etc/systemd/system/ (for admin-created or admin-overridden units - checked first) and /lib/systemd/system/ (installed by packages). Whenever you hand-edit or add a unit file, you must run systemctl daemon-reload afterward - systemd caches parsed unit files in memory, and won't notice a change on disk until told to re-read them.

$ systemctl enable --now sshd
Created symlink /etc/systemd/system/multi-user.target.wants/sshd.service.

That output line is enable doing its actual work: it creates a symlink inside a target's .wants directory, which is literally how systemd remembers "start this unit whenever that target is reached." --now additionally starts it immediately, so you don't have to wait for the next boot to see it running.

Warning: start and enable control two independent things and mixing them up is one of the most common systemd mistakes: start affects only the current boot - the service runs now, but won't come back after a reboot. enable only affects future boots - it won't start the service right now, only arrange for it to start next time. A service you just installed almost always needs both, which is exactly why enable --now exists as a single combined command.