systemd is the init system used by virtually all major Linux distributions today — Ubuntu, Debian, RHEL, Fedora, Rocky Linux, and more. It manages the boot process, handles services, mounts filesystems, and manages logging. Understanding systemd is essential for any modern Linux sysadmin.
What Is systemd?
systemd is PID 1 — the first process the kernel starts. It then starts everything else in parallel, which makes modern Linux boot much faster than older init systems. It organizes system resources as units: services, sockets, timers, mounts, and more.
systemctl --version
ps -p 1 # Confirm PID 1 is systemd
Managing Services with systemctl
systemctl status nginx # Show service status, recent logs
systemctl start nginx # Start immediately
systemctl stop nginx # Stop immediately
systemctl restart nginx # Stop + start
systemctl reload nginx # Reload config (no downtime if supported)
systemctl enable nginx # Start at boot
systemctl disable nginx # Do not start at boot
systemctl enable --now nginx # Enable AND start immediately
systemctl is-active nginx # Prints "active" or "inactive" (exit code 0/1)
systemctl is-enabled nginx # Prints "enabled" or "disabled"
Listing Units
systemctl list-units # All active units
systemctl list-units --type=service # Services only
systemctl list-units --state=failed # Failed units
systemctl list-unit-files # All installed unit files
systemctl list-unit-files --type=service | grep enabled # Enabled services
Viewing Logs with journalctl
systemd captures all service output in the journal:
journalctl # All logs (newest at bottom)
journalctl -b # Logs from current boot only
journalctl -b -1 # Logs from previous boot
journalctl -u nginx # Logs for nginx service
journalctl -u nginx -n 50 # Last 50 lines for nginx
journalctl -u nginx -f # Follow (live tail)
journalctl --since "2026-04-01" # Logs since date
journalctl --since "1 hour ago" # Last hour
journalctl -p err # Only errors
journalctl -k # Kernel messages only
Writing a systemd Service Unit
Unit files live in /etc/systemd/system/. Here is a complete example for a Node.js application:
sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My Node.js Application
After=network.target
Wants=network-online.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal
Environment=NODE_ENV=production PORT=3000
[Install]
WantedBy=multi-user.target
sudo systemctl daemon-reload # Reload unit files after editing
sudo systemctl enable --now myapp # Enable and start
sudo systemctl status myapp # Verify
Unit File Directives Explained
- [Unit] — metadata and ordering.
After=means start after these units are up. - [Service] — the actual service definition.
Type=simple— process stays in foreground (most common).Restart=on-failure— auto-restart if the process exits with error.RestartSec=5— wait 5 seconds before restarting.- [Install] — defines when to enable.
multi-user.target= normal multi-user mode.
Timers (Replacing Cron)
systemd timers are a modern alternative to cron, with better logging and dependency handling:
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl enable --now backup.timer
systemctl list-timers # List all active timers
Analyzing Boot Performance
systemd-analyze # Total boot time
systemd-analyze blame # Time per unit
systemd-analyze critical-chain # Bottleneck chain
systemd-analyze plot > boot.svg # Visual boot chart
Target Units (Replacing Runlevels)
systemctl get-default # Default target (usually graphical or multi-user)
sudo systemctl set-default multi-user.target # Boot to text mode
sudo systemctl isolate rescue.target # Switch to rescue mode
Dependency Management
systemctl list-dependencies nginx # What nginx depends on
systemctl list-dependencies --reverse nginx # What depends on nginx
Summary
systemd is the backbone of modern Linux systems. Use systemctl to manage services, journalctl to read logs, and unit files to define your own services. Writing a clean service unit with Restart=on-failure and proper logging ensures your applications are resilient and debuggable in production.
Frequently Asked Questions
-
What is the difference between
systemctl restartandsystemctl reload?
systemctl restart servicenamestops the service completely and then starts it fresh — all in-flight connections or sessions are dropped.systemctl reload servicenamesends a SIGHUP signal to the running process, instructing it to re-read its configuration without stopping. Reload causes zero downtime when the service supports it (Nginx, Apache, and PostgreSQL all handle SIGHUP gracefully). If a service does not implement in-place reload,reloadwill fail or do nothing — check the unit file for aExecReload=directive to confirm support. Usereloadfor configuration changes in production; userestartwhen you need to apply binary updates or the service is in a bad state. -
Why does my service start but immediately stop?
The most common cause is an error in the startup command or the service configuration file. Check the path inExecStart=is correct and the binary is executable. Then read the logs — this is almost always where the answer is:
Look for lines markedjournalctl -u your-service-name -n 50 --no-pagerFAILEDor any error message from the application itself. Also verify that anyEnvironmentFile=or configuration files referenced by the service actually exist and are readable by the service's user. -
How do I know if a service is set to start at boot?
Usesystemctl is-enabled servicename. It returnsenabledif the service will start at boot,disabledif it will not, orstaticif it is controlled by another unit. To enable a service for boot:sudo systemctl enable servicename. To enable and start it immediately in one command:sudo systemctl enable --now servicename. Note thatsystemctl startstarts the service now but does not make it persistent across reboots — you needenablefor that. -
What is the difference between
Type=simpleandType=forking?
Type=simple(the default) tells systemd that the process listed inExecStart=is the main process of the service and stays in the foreground. systemd tracks it directly.Type=forkingis for traditional Unix daemons that fork a child process and then have the parent exit. systemd waits for the parent to exit and then tracks the child. Setting the wrong type causes problems: if a forking daemon is declared assimple, systemd thinks the service died when the parent exits and may restart it. When in doubt, check the daemon's documentation or look at its official upstream systemd unit file. -
How do I run a systemd service as a specific user?
In the[Service]section of the unit file, add:
systemd will drop privileges and run the service as that user before executing[Service] User=myappuser Group=myappgroupExecStart=. The user must exist on the system. For security, create a dedicated system user with no login shell:sudo useradd -r -s /usr/sbin/nologin myappuser. You can also combine this withWorkingDirectory=to set the working directory andEnvironmentFile=to load secrets from a file owned and readable only by that user.