The most surprising thing about systemd’s boot process is that it doesn’t actually do anything until the kernel tells it to.
Let’s watch it in action. Imagine a typical boot. The BIOS/UEFI hands off to the bootloader (like GRUB), which then loads the kernel and an initial RAM disk (initrd). The kernel initializes hardware, mounts the root filesystem, and then, crucially, it executes /sbin/init. On most modern Linux systems, /sbin/init is a symlink to systemd. So, systemd’s journey begins not with a grand entrance, but as the designated successor to the old init process.
Once systemd is running, it doesn’t just execute scripts sequentially like its predecessors. Instead, it reads a set of "unit files" that describe services, devices, mount points, and more. These units have dependencies defined, and systemd is a master of parallel execution. It starts building a dependency graph and, using the information in these unit files, launches everything that can run concurrently. Think of it like a highly efficient project manager who knows exactly which tasks can be done at the same time and which need to wait for others.
Here’s a simplified look at the core components and how they interact:
-
Unit Files: These are the configuration files for
systemd. They live in directories like/etc/systemd/system/and/usr/lib/systemd/system/. A common one is a service file, like/etc/systemd/system/nginx.service.[Unit] Description=Nginx web server After=network.target [Service] ExecStart=/usr/sbin/nginx -g 'daemon off;' Restart=always User=nginx Group=nginx [Install] WantedBy=multi-user.targetThe
[Unit]section defines metadata and dependencies.After=network.targetmeans Nginx should only start after the network is up. The[Service]section defines how to run the actual service.[Install]tellssystemdhow to enable this service to start at boot, in this case, by being part of themulti-user.target(the standard runlevel for a non-graphical, multi-user system). -
Targets: These are special units that act like runlevels.
multi-user.targetis what you typically aim for.graphical.targetpulls inmulti-user.targetand adds graphical elements.systemd-update-utmp.serviceis a unit thatsystemdstarts early to ensure the system’s user login information is updated. -
The
systemctlCommand: This is your primary tool for interacting withsystemd.- To see the status of all active units:
systemctl list-units - To see all installed units (active and inactive):
systemctl list-unit-files - To start a service:
systemctl start nginx.service - To stop a service:
systemctl stop nginx.service - To enable a service to start at boot:
systemctl enable nginx.service - To disable a service from starting at boot:
systemctl disable nginx.service - To reboot the system gracefully:
systemctl reboot - To power off the system:
systemctl poweroff
- To see the status of all active units:
systemd’s core mechanism for managing services is called "socket activation." Instead of starting a service immediately at boot, systemd can wait until a network socket it’s responsible for receives an incoming connection. When that happens, systemd then starts the specific service designed to handle that socket. This means services that aren’t immediately needed, or only needed sporadically, don’t consume resources until they are actually invoked, making the boot process much more efficient and the running system leaner.
The systemd-journald service is also a critical piece of the puzzle, acting as a centralized logging daemon. It collects logs from all other services and the kernel, making them accessible via the journalctl command. This unified logging approach replaces traditional syslog and provides structured, timestamped log entries that are much easier to search and analyze.
When you execute systemctl start nginx.service, systemd looks at the nginx.service unit file. It checks the After= directive to ensure network.target is active. If not, it starts the units required for network.target. Once dependencies are met, it spawns a new process using fork() and execve() to run /usr/sbin/nginx -g 'daemon off;' as the specified nginx user. It then monitors this process, restarting it if it crashes due to the Restart=always directive.
The real magic of systemd lies in its declarative, dependency-driven model rather than imperative scripting. It doesn’t just run commands; it manages the state of the system. When you enable a service, systemd creates symlinks in the appropriate *.target.wants/ directories, effectively telling itself, "When multi-user.target is activated, ensure nginx.service is also started."
The next concept you’ll likely grapple with is managing complex service dependencies, especially when dealing with custom applications or intricate network configurations.