systemd is the init system on every modern Linux. A service unit = .service file describing how to start/stop/restart a daemon. Replaces supervisord, pm2 (for Node), rc.d. Auto-start on boot, auto-restart on crash, journalctl for logs, systemctl for control. Minimal unit — 10 lines.
Below: step-by-step, working examples, common pitfalls, FAQ.
systemctl daemon-reload — reload unitssystemctl enable myapp — auto-start on bootsystemctl start myapp + systemctl statusjournalctl -u myapp -f (live tail)| Scenario | Config |
|---|---|
| Simple Node.js service | [Unit]
Description=My App
After=network.target
[Service]
Type=simple
User=nodejs
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target |
| Python with venv | [Service]
Type=simple
User=app
WorkingDirectory=/opt/myapp
ExecStart=/opt/myapp/venv/bin/python /opt/myapp/app.py
Environment="PATH=/opt/myapp/venv/bin"
Restart=on-failure |
| Systemd hardening (sandboxing) | [Service]
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/log/myapp |
| Timer (cron-like) | # /etc/systemd/system/backup.timer
[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true
[Install]
WantedBy=timers.target |
| Reload config without restart | ExecReload=/bin/kill -HUP $MAINPID
# systemctl reload myapp |
Environment="KEY=value", not bash syntaxuseradd -r -s /bin/false nodejsjournalctl -u myappsystemctl daemon-reload after a unit change → stale configsystemd — built-in Linux, zero deps. pm2 — specialized for Node.js (cluster, zero-downtime reload). For simple apps — systemd.
on-failure (restart on non-zero exit) — standard. always — restart even on normal exit (useful for daemons). no — manual only.
<code>TimeoutStopSec=30s</code> — systemd waits 30 s before SIGKILL. App must handle SIGTERM and exit cleanly.
journald auto-rotates. Settings: <code>/etc/systemd/journald.conf</code> → SystemMaxUse=1G, MaxRetentionSec=30d.