systemd is the init system and service manager used by most modern Linux distributions. It runs as process ID 1, the first user-space process the kernel starts, and is responsible for bringing the system up, supervising services and shutting everything down in a controlled order.
In system initialization, systemd replaced the script-based SysV init model with declarative unit files and a dependency engine that starts independent services in parallel. Since its first release in 2010 it has also grown into a suite of components for logging, device management, login sessions, networking and time synchronization, which is why it is both central and frequently debated.
How the service manager boots a Linux system
After the bootloader, typically GRUB, loads the kernel and the initial RAM disk, the kernel mounts the root filesystem and executes /sbin/init, which on a systemd system is a link to the systemd binary. systemd then reads all unit files, builds a dependency graph and works toward a default target, usually multi-user.target on servers or graphical.target on desktops.
Instead of running numbered scripts one after another, systemd starts every unit whose dependencies are satisfied at the same time. Socket activation goes further: systemd opens a listening socket itself and starts the service only when the first connection arrives, so clients can connect before the daemon has finished loading. Every service runs in its own control group (cgroup), which lets systemd track and stop all of its processes, including forked children.
| SysV runlevel | Target | System state |
|---|---|---|
| 0 | poweroff.target | Shut down and power off |
| 1 | rescue.target | Single-user maintenance mode |
| 3 | multi-user.target | Full multi-user system without a graphical session |
| 5 | graphical.target | Multi-user system with a display manager |
| 6 | reboot.target | Restart the machine |
There is also emergency.target, which provides a root shell with the root filesystem mounted read-only and almost no services running. It is the last resort when even rescue mode fails.
Units, dependencies and targets
Everything systemd manages is a unit, described by an INI-style text file whose suffix names its type. Units declare relationships rather than steps, and the dependency engine derives the start order from them.
| Unit type | Suffix | What it manages |
|---|---|---|
| Service | .service | A daemon or one-off process |
| Socket | .socket | A listening socket for socket activation |
| Target | .target | A named group of units and a synchronization point |
| Timer | .timer | Time-based activation, an alternative to cron |
| Mount | .mount | A filesystem mount point |
| Path | .path | Activation when a file or directory changes |
| Slice | .slice | A cgroup level for resource limits |
Two kinds of directives must not be confused. Requirement dependencies such as Wants= and Requires= decide which units are pulled in, while ordering dependencies such as After= and Before= decide only the sequence. Requires=database.service without After=database.service starts both units in parallel, a frequent source of race conditions at boot.
Unit files shipped by packages live in /usr/lib/systemd/system, while administrator changes belong in /etc/systemd/system, which takes precedence. The command systemctl edit nginx.service creates a drop-in override file that survives package updates, unlike edits to the vendor file.
Service types and supervision
The Type= setting tells systemd when a service counts as started, which matters for every unit ordered after it. Choosing the wrong type makes dependent services start too early or makes systemd wait for a readiness signal that never comes.
| Type | Considered started when | Typical use |
|---|---|---|
| simple | The main process has been forked | Programs that run in the foreground |
| exec | The binary has been executed successfully | Like simple, but reports a missing binary as failure |
| forking | The parent process exits after forking | Legacy daemons that background themselves |
| oneshot | The process has exited | Setup tasks and scripts |
| notify | The service sends READY=1 through sd_notify | Daemons with explicit readiness reporting |
Supervision is configured in the same file. Restart=on-failure with RestartSec=5 restarts a crashed service after five seconds, while the default rate limit of five starts within 10 seconds stops endless restart loops. Hardening options such as `ProtectSystem=strict`, `PrivateTmp=yes` and `NoNewPrivileges=yes` confine a service without changing its code, and systemd-analyze security scores how exposed each service is.
Components beyond PID 1
The systemd project ships many optional daemons that integrate with the service manager. Distributions choose which ones to enable, so the presence of systemd does not automatically mean that all of them are in use.
- systemd-journald collects kernel, service and application logs in an indexed binary journal, read with journalctl.
- systemd-udevd handles device events and creates device nodes; udev was merged into the project in 2012.
- systemd-logind tracks user sessions, seats and power keys.
- systemd-networkd and systemd-resolved configure networking and DNS resolution, mainly on servers and containers.
- systemd-timesyncd provides simple SNTP time synchronization.
The central management command is systemctl: systemctl status, start, stop, restart, enable --now and daemon-reload after editing unit files. systemd-analyze blame lists units by start time, which helps diagnose slow boots.
Adoption, criticism and alternatives
Fedora became the first major distribution to use systemd by default in 2011, and Debian, Ubuntu, RHEL, SUSE and Arch Linux followed by 2015. Its supporters point to fast parallel boot, reliable process tracking and consistent configuration across distributions.
Critics object to the broad scope of the project, its binary log format and the tight coupling of its components, and some distributions deliberately avoid it. The comparison below places systemd among the main init systems.
| Init system | Configuration | Parallel start | Typical users |
|---|---|---|---|
| systemd | Declarative unit files | Yes, dependency-driven | Most mainstream distributions |
| SysV init | Shell scripts in /etc/init.d | No, sequential | Older and legacy systems |
| OpenRC | Shell-based scripts with dependencies | Optional | Gentoo, Alpine Linux |
| runit | Small run scripts per service | Yes | Void Linux, minimal containers |
In plain words
When a Linux computer starts, something must switch on all the background programs in the right order. systemd is that conductor. It knows which program needs which other program and starts as many as possible at once.
It also keeps watching them. If a program crashes, systemd can restart it. When the computer shuts down, it stops everything cleanly. systemd is the manager that starts, watches and stops services, so the rest of the system can run reliably.
A real-world example
A small analytics team runs a Python web API on an Ubuntu server. At first it is started by hand inside a terminal session, and it disappears whenever the server reboots or the program crashes. The administrator writes a 15-line unit file with Type=exec, a dedicated service user, After=network-online.target postgresql.service, Wants= for both, and Restart=on-failure with RestartSec=5.
After systemctl daemon-reload and systemctl enable --now api.service, the API starts automatically at boot, but only after PostgreSQL. A memory error that crashes it twice a week now causes about five seconds of downtime instead of an outage until someone notices. The logs land in the journal, and journalctl -u api.service --since today shows each crash with its stack trace.