Systemd is the init system and service manager for most modern Linux distributions. Master systemctl to control your system.
Service Control
Basic Commands
# Start a service
sudo systemctl start nginx
# Stop a service
sudo systemctl stop nginx
# Restart a service
sudo systemctl restart nginx
# Reload configuration (if supported)
sudo systemctl reload nginx
# Reload or restart (safer)
sudo systemctl reload-or-restart nginx
# Enable at boot
sudo systemctl enable nginx
# Disable at boot
sudo systemctl disable nginx
# Enable and start
sudo systemctl enable --now nginx
# Disable and stop
sudo systemctl disable --now nginxService Status
# Check status
systemctl status nginx
# Check if running
systemctl is-active nginx
# Check if enabled
systemctl is-enabled nginx
# Check if failed
systemctl is-failed nginx
# List all services
systemctl list-units --type=service
# List running services
systemctl list-units --type=service --state=running
# List failed services
systemctl --failed
# List enabled services
systemctl list-unit-files --type=service --state=enabledUnderstanding Unit Files
Unit File Locations
/etc/systemd/system/ # Local configuration (highest priority)
/run/systemd/system/ # Runtime units
/lib/systemd/system/ # Distribution-provided units
/usr/lib/systemd/system/ # Package-installed units (RHEL)Basic Service Unit
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
After=network.target
[Service]
Type=simple
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/start.sh
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.targetUnit Sections
[Unit]
[Unit]
Description=Human-readable description
Documentation=https://example.com/docs
After=network.target postgresql.service
Requires=postgresql.service # Hard dependency
Wants=redis.service # Soft dependency[Service]
[Service]
Type=simple # Main process stays in foreground
# Type=forking # Traditional daemon (forks)
# Type=oneshot # Short-lived task
# Type=notify # Sends notification when ready
ExecStartPre=/opt/myapp/pre-start.sh
ExecStart=/opt/myapp/start.sh
ExecStartPost=/opt/myapp/post-start.sh
ExecStop=/opt/myapp/stop.sh
ExecReload=/bin/kill -HUP $MAINPID
User=appuser
Group=appgroup
WorkingDirectory=/opt/myapp
Environment="NODE_ENV=production"
EnvironmentFile=/etc/myapp/env
Restart=on-failure
RestartSec=5
TimeoutStartSec=30
TimeoutStopSec=30[Install]
[Install]
WantedBy=multi-user.target # Start in multi-user mode
# WantedBy=graphical.target # Start in graphical modeCreating Custom Services
Simple Web Application
# /etc/systemd/system/webapp.service
[Unit]
Description=Node.js Web Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node /var/www/myapp/server.js
Restart=on-failure
RestartSec=10
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=webapp
Environment=NODE_ENV=production PORT=3000
[Install]
WantedBy=multi-user.targetWith Environment File
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application
[Service]
Type=simple
User=appuser
EnvironmentFile=/etc/myapp/.env
ExecStart=/opt/myapp/bin/start
Restart=always
[Install]
WantedBy=multi-user.target# /etc/myapp/.env
DATABASE_URL=postgresql://localhost/mydb
SECRET_KEY=your-secret-key
DEBUG=falseEnabling the Service
# Reload systemd to read new unit
sudo systemctl daemon-reload
# Enable and start
sudo systemctl enable --now myapp
# Check status
systemctl status myapp
# View logs
journalctl -u myapp -fService Security Hardening
[Service]
# User/Group
User=appuser
Group=appgroup
DynamicUser=true # Allocate user dynamically
# Filesystem restrictions
ProtectSystem=strict # Mount /usr, /boot read-only
ProtectHome=true # Hide /home, /root, /run/user
PrivateTmp=true # Private /tmp
ReadWritePaths=/var/lib/myapp # Allow write here
ReadOnlyPaths=/etc/myapp # Read-only access
# Network restrictions
PrivateNetwork=true # No network access
RestrictAddressFamilies=AF_INET AF_INET6 # IPv4/6 only
# System call restrictions
SystemCallFilter=@system-service # Whitelist system calls
SystemCallArchitectures=native # Native arch only
# Other restrictions
NoNewPrivileges=true # No privilege escalation
ProtectKernelTunables=true # Protect /proc, /sys
ProtectControlGroups=true # Protect cgroupsJournalctl (Logs)
# View logs for a service
journalctl -u nginx
# Follow logs (tail -f)
journalctl -u nginx -f
# Since boot
journalctl -u nginx -b
# Last 100 lines
journalctl -u nginx -n 100
# Since time
journalctl -u nginx --since "1 hour ago"
journalctl -u nginx --since "2024-01-01 00:00:00"
# Priority (error and above)
journalctl -u nginx -p err
# Output as JSON
journalctl -u nginx -o json
# Disk usage
journalctl --disk-usage
# Clear old logs
sudo journalctl --vacuum-time=7d
sudo journalctl --vacuum-size=500MSystem Targets
# List targets
systemctl list-units --type=target
# Get current target
systemctl get-default
# Set default target
sudo systemctl set-default multi-user.target # Text mode
sudo systemctl set-default graphical.target # GUI mode
# Change target now
sudo systemctl isolate multi-user.target
# Common targets:
# poweroff.target - Shutdown
# rescue.target - Single user / rescue mode
# multi-user.target - Multi-user text mode
# graphical.target - GUI mode
# reboot.target - RebootAnalyzing Boot
# Analyze boot time
systemd-analyze
# Blame (time per service)
systemd-analyze blame
# Critical chain (boot path)
systemd-analyze critical-chain
# Plot boot chart
systemd-analyze plot > boot.svg intermediate System Administration 25 min read
Related Tutorials
systemdsystemctlserviceslinux servicesinit system