Manage services with systemd
On Debian 13, systemd starts services, supervises them and centralises their logs. Knowing how to drive it avoids rebooting the whole VPS just to restart Nginx or an application. These are the systemd commands on Debian 13.
Basic commands
| Action | Command |
|---|---|
| Detailed status | systemctl status nginx |
| Start now | sudo systemctl start nginx |
| Stop now | sudo systemctl stop nginx |
| Restart | sudo systemctl restart nginx |
| Reload configuration | sudo systemctl reload nginx |
| Enable at boot | sudo systemctl enable nginx |
| Disable at boot | sudo systemctl disable nginx |
| List failures | systemctl --failed |
start acts immediately; enable creates the link that starts the service at boot. They are independent: a service can run without being enabled, and the reverse. reload is preferable to restart when the software re-reads its configuration without dropping connections; nginx -t must always come before a reload.
To list what is actually running:
systemctl list-units --type=service --state=running
systemctl is-enabled nginxCreate a unit for your application
An app started by hand dies when the terminal closes. A unit starts it at boot and restarts it after a crash. Create /etc/systemd/system/my-app.service:
[Unit]
Description=My Node.js application
After=network.target
[Service]
Type=simple
User=app
WorkingDirectory=/srv/my-app
EnvironmentFile=/etc/my-app.env
ExecStart=/usr/bin/node /srv/my-app/index.js
Restart=on-failure
RestartSec=5
NoNewPrivileges=true
[Install]
WantedBy=multi-user.targetExecStart requires an absolute path and does not go through a shell. EnvironmentFile must be readable by the service user, with 600 permissions if it holds secrets. Restart=on-failure avoids restarting a service that exits cleanly in a loop.
Then enable it:
sudo systemctl daemon-reload
sudo systemctl enable --now my-app
sudo systemctl status my-appdaemon-reload is mandatory after any unit change.
Read state and logs
systemctl status my-app --no-pager
journalctl -u my-app -f
journalctl -u my-app --since "30 min ago" -p errstatus shows the exit code, main PID and last lines. An activating (auto-restart) state means a restart loop: read the lines just before the failure. After a fix, sudo systemctl reset-failed my-app clears the failure counter.
Best practices
- Do not edit units shipped by packages. Use
sudo systemctl edit nginxto create an override in/etc/systemd/system/nginx.service.d/. - Use
systemctl maskinstead ofdisableto prevent a service from starting, even as a dependency. - After a change, test a full VPS reboot and check
systemctl --failed.
Verify
systemctl is-active my-app
systemctl is-enabled my-app
systemctl show -p MainPID -p Restart my-appis-active must answer active, is-enabled must answer enabled, and the PID must change after a restart. If the service keeps restarting, look for the error in journalctl -u my-app -n 100 before changing the unit.
Advertisement
Was this article helpful?
Read next
- Change the SSH port safelyMove SSH to another port by opening the firewall first and testing from a second session.
- Schedule tasks with cronWrite a reliable crontab, log its output and choose between cron and systemd timers.
- Protect SSH with Fail2banInstall Fail2ban on Debian 13, tune the sshd jail and avoid banning yourself.