systemd is the init system and service manager on almost every modern Linux distribution — Ubuntu, Debian, Fedora, CentOS, Arch, and more. If you administer a Linux server, you interact with systemd every day whether you realize it or not.
Every time you run systemctl start nginx or journalctl -f, you are using systemd. This guide covers everything you need to know — from basic service management to creating your own unit files and replacing cron jobs with systemd timers.
What is systemd?
systemd is the first process that runs when Linux boots (PID 1). It is responsible for:
- Starting and stopping services (nginx, sshd, docker, etc.)
- Managing dependencies (start database before web server)
- Logging (journald replaces syslog)
- Scheduling tasks (timers as cron alternative)
- Mounting filesystems
- Managing network, DNS, time sync, and more
Before systemd, Linux used SysV init scripts — shell scripts in /etc/init.d/ that were fragile and inconsistent. systemd replaced this with a unified, declarative system.
Managing Services
Basic Commands
# Start a service
sudo systemctl start nginx
# Stop a service
sudo systemctl stop nginx
# Restart (stop then start)
sudo systemctl restart nginx
# Reload config without restarting (if supported)
sudo systemctl reload nginx
# Check status
systemctl status nginx
# Enable (start on boot)
sudo systemctl enable nginx
# Disable (don't start on boot)
sudo systemctl disable nginx
# Enable and start in one command
sudo systemctl enable --now nginx
Check Service Status
$ systemctl status nginx
● nginx.service - A high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
Active: active (running) since Tue 2026-04-01 10:30:00 CDT
Process: 1234 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
Main PID: 1235 (nginx)
Tasks: 5 (limit: 18838)
Memory: 12.4M
CPU: 234ms
CGroup: /system.slice/nginx.service
├─1235 "nginx: master process /usr/sbin/nginx"
└─1236 "nginx: worker process"
Key things to look at:
- Active:
active (running)means it is working.failedmeans it crashed. - Loaded:
enabledmeans it starts on boot - Main PID: The process ID
- Memory/CPU: Resource usage
List All Services
# All loaded services
systemctl list-units --type=service
# All services (including inactive)
systemctl list-units --type=service --all
# Only failed services
systemctl list-units --type=service --state=failed
# Check if a specific service is active
systemctl is-active nginx
# Check if enabled on boot
systemctl is-enabled nginx
Creating Custom Services
When you write your own application or script that needs to run as a service, you create a unit file.
Unit File Location
/etc/systemd/system/— your custom services go here/lib/systemd/system/— package-installed services (don't edit these)
Basic Service Unit File
Create /etc/systemd/system/myapp.service:
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/python3 /opt/myapp/server.py
Restart=always
RestartSec=5
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
Then activate it:
sudo systemctl daemon-reload # Reload unit files
sudo systemctl enable --now myapp # Enable and start
systemctl status myapp # Verify
Section Breakdown
[Unit] — Metadata and dependencies
| Directive | Purpose |
|---|---|
Description |
Human-readable name |
After |
Start after these units |
Requires |
Hard dependency — if it fails, this fails too |
Wants |
Soft dependency — start if available |
[Service] — How to run it
| Directive | Purpose |
|---|---|
Type |
simple (default), forking, oneshot, notify |
ExecStart |
Command to run |
ExecStartPre |
Command to run before starting |
ExecReload |
Command for systemctl reload |
Restart |
always, on-failure, no |
RestartSec |
Seconds to wait before restart |
User / Group |
Run as this user |
WorkingDirectory |
Set the working directory |
Environment |
Set environment variables |
EnvironmentFile |
Load env vars from a file |
[Install] — When to start
| Directive | Purpose |
|---|---|
WantedBy=multi-user.target |
Start in normal multi-user mode (most services) |
WantedBy=graphical.target |
Start when GUI is ready |
Real Example: Node.js App
[Unit]
Description=SamNet API Server
After=network.target
[Service]
Type=simple
User=samnet
WorkingDirectory=/opt/samnet-api
ExecStart=/usr/bin/node /opt/samnet-api/index.js
Restart=on-failure
RestartSec=10
StandardOutput=journal
StandardError=journal
Environment=PORT=3000
Environment=NODE_ENV=production
[Install]
WantedBy=multi-user.target
Real Example: Python with Virtual Environment
[Unit]
Description=Flask Web App
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/flask-app
ExecStart=/opt/flask-app/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
Journalctl — Reading Logs
systemd's logging system is called journald. It replaces traditional log files with a structured, indexed journal.
Basic Usage
# All logs (paged)
journalctl
# Follow logs in real time (like tail -f)
journalctl -f
# Logs for a specific service
journalctl -u nginx
# Follow a specific service
journalctl -u nginx -f
# Last 50 lines
journalctl -u nginx -n 50
# Logs since last boot
journalctl -b
# Logs from previous boot
journalctl -b -1
Filtering by Time
# Since a specific time
journalctl --since "2026-04-01 10:00:00"
# Last hour
journalctl --since "1 hour ago"
# Last 24 hours
journalctl --since "yesterday"
# Time range
journalctl --since "2026-04-01" --until "2026-04-02"
Filtering by Priority
# Only errors and worse
journalctl -p err
# Warnings and worse
journalctl -p warning
# Priority levels: emerg, alert, crit, err, warning, notice, info, debug
Output Formats
# JSON output (great for parsing)
journalctl -u nginx -o json-pretty
# Short (default, syslog-like)
journalctl -u nginx -o short
# Verbose (all fields)
journalctl -u nginx -o verbose
Disk Usage
# How much space journals use
journalctl --disk-usage
# Clean up old logs (keep last 1GB)
sudo journalctl --vacuum-size=1G
# Keep only last 30 days
sudo journalctl --vacuum-time=30d
systemd Timers (Cron Alternative)
systemd timers are a modern alternative to cron. They offer better logging, dependency management, and can trigger on events (not just time).
Creating a Timer
You need two files: a service unit (what to run) and a timer unit (when to run it).
Step 1: Create the service — /etc/systemd/system/backup.service:
[Unit]
Description=Daily Backup
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
Step 2: Create the timer — /etc/systemd/system/backup.timer:
[Unit]
Description=Run backup daily at 2 AM
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Step 3: Enable the timer (not the service):
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Timer Syntax
# Every day at midnight
OnCalendar=daily
# Every day at 3:30 AM
OnCalendar=*-*-* 03:30:00
# Every Monday at 6 AM
OnCalendar=Mon *-*-* 06:00:00
# Every 15 minutes
OnCalendar=*:0/15
# First of every month
OnCalendar=*-*-01 00:00:00
List Active Timers
systemctl list-timers --all
Timer vs Cron
| Feature | Cron | systemd Timer |
|---|---|---|
| Logging | Manual (redirect to file) | Automatic (journalctl) |
| Missed runs | Lost forever | Persistent=true catches up |
| Dependencies | None | Full systemd dependency system |
| Resource control | None | CPU/memory limits via cgroups |
| Randomized delay | No | RandomizedDelaySec |
| Setup | One line | Two files |
For more cron syntax examples, check our Cron Job Examples guide or use the Cron Expression Generator.
Useful systemd Commands Cheat Sheet
# Reload all unit files after changes
sudo systemctl daemon-reload
# See all failed units
systemctl --failed
# See boot time breakdown
systemd-analyze
# See which services slow down boot
systemd-analyze blame
# Kill a service and all its children
sudo systemctl kill nginx
# Mask a service (prevent starting entirely)
sudo systemctl mask nginx
# Unmask
sudo systemctl unmask nginx
# See all dependencies of a service
systemctl list-dependencies nginx
# Edit a service's override (safe way to customize)
sudo systemctl edit nginx
Related Tools
Use our Chmod Calculator to set correct permissions on your service scripts and unit files.