Systemd for Self-Hosters: Managing Services on Linux
Systemd manages services on modern Linux. Understanding it is essential for self-hosting: start, stop, enable, and monitor your applications.
What Is Systemd?
Systemd is the init system and service manager on most modern Linux distributions. It starts services at boot, manages their lifecycle, and handles logging.
Essential Commands
Status
systemctl status service-name
Shows if a service is running, its PID, memory usage, and recent logs.
Start/Stop
systemctl start service-name
systemctl stop service-name
Restart
systemctl restart service-name (hard restart)
systemctl reload service-name (reload configuration without restart, if supported)
Enable/Disable
systemctl enable service-name (start at boot)
systemctl disable service-name (don't start at boot)
List Services
systemctl list-units --type=service
Unit Files
Service configuration lives in unit files. View with:
systemctl cat service-name
Custom Unit File
Create /etc/systemd/system/myapp.service:
[Unit]
Description=My Application
After=network.target
[Service]
ExecStart=/usr/bin/myapp
Restart=always
User=deploy
EnvironmentFile=/etc/myapp/env
[Install]
WantedBy=multi-user.target
Then:
systemctl daemon-reload
systemctl enable --now myapp
Journald (Logging)
Systemd includes journald for centralized logging.
View Logs
journalctl -u service-name (all logs for a service)
journalctl -u service-name -f (follow/tail logs)
journalctl -u service-name --since "1 hour ago"
journalctl -u service-name -p err (only errors)
Log Rotation
Configure in /etc/systemd/journald.conf:
SystemMaxUse=500M (limit total log size)
MaxRetentionSec=30day (keep logs for 30 days)
Podman and Systemd
Podman integrates beautifully with systemd. Generate a unit file from a running container:
podman generate systemd --name mycontainer > /etc/systemd/system/mycontainer.service
Now your container starts at boot, restarts on failure, and logs go to journald.
Timers (Cron Alternative)
Systemd timers are a modern alternative to cron:
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
Advantages over cron: