Every service on a modern Linux server — Nginx, MariaDB, PHP-FPM, SSH, your own Node or Python app — is managed by systemd. Learn six commands and you can start, stop, inspect and debug all of them the same way.
The six commands
sudo systemctl status nginx # running? since when? last log lines
sudo systemctl start nginx
sudo systemctl stop nginx
sudo systemctl restart nginx # stop then start — drops connections briefly
sudo systemctl reload nginx # re-read config without dropping connections
sudo systemctl enable nginx # start at bootenable --now does both enable and start in one go; disable --now the reverse. status is the one to run first whenever something is wrong: it shows whether the service is active, failed or stopped, how long it has been up, and the last ten log lines.
Which services exist
systemctl list-units --type=service --state=running # what is running now
systemctl list-unit-files --type=service --state=enabled # what starts at boot
systemctl --failed # anything that crashedThe second list is worth reading on a new server: an FTP daemon or a print service you never use is attack surface for nothing.
Reading logs with journalctl
systemd collects the output of every service into the journal. journalctl queries it:
sudo journalctl -u nginx # everything nginx ever logged
sudo journalctl -u nginx -n 50 # last 50 lines
sudo journalctl -u nginx -f # follow live, like tail -f
sudo journalctl -u nginx --since "1 hour ago"
sudo journalctl -u nginx --since "2026-09-20 14:00" --until "2026-09-20 15:00"
sudo journalctl -p err -b # all errors since the last boot
sudo journalctl -k # kernel messages (disk errors, OOM kills)Add --no-pager when piping to grep. The -p err -b form is the fastest way to find out why a server is misbehaving: it lists every error from every service since boot on one screen.
Note that Nginx, Apache and PHP-FPM write their request logs to files under /var/log/ — the journal has their start/stop/crash messages, not every HTTP request. Where each log lives is in Linux log files and how to read them.
Keeping the journal from filling the disk
journalctl --disk-usage
sudo journalctl --vacuum-time=30d # drop entries older than 30 daysMake it permanent in /etc/systemd/journald.conf: SystemMaxUse=500M.
Run your own application as a service
The reason to learn this: a Node, Python or Go app started by hand dies when you log out, and does not come back after a reboot. A unit file fixes both. Create /etc/systemd/system/myapp.service:
[Unit]
Description=My application
After=network.target
[Service]
User=deploy
WorkingDirectory=/var/www/myapp
ExecStart=/usr/bin/node server.js
Restart=on-failure
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/var/www/myapp/.env
[Install]
WantedBy=multi-user.targetThen:
sudo systemctl daemon-reload # after creating or editing any unit
sudo systemctl enable --now myapp
sudo systemctl status myapp
sudo journalctl -u myapp -fRestart=on-failure restarts it if it crashes; User= keeps it from running as root; EnvironmentFile keeps secrets out of the unit. That is a production-grade process manager in twelve lines, with no PM2 or supervisor to install.
A PHP queue worker for Laravel looks the same with ExecStart=/usr/bin/php /var/www/app/artisan queue:work --sleep=3 --tries=3.
Timers instead of cron
systemd can also run things on a schedule. A pair of files — backup.service with the command, and backup.timer with OnCalendar=daily — replaces a cron line, with the advantage that journalctl -u backup shows exactly what happened each run. Cron is still fine and simpler for one-liners; see scheduling tasks with cron.
When a service will not start
sudo systemctl status nginx # read the last lines — usually the reason
sudo journalctl -u nginx -n 100 # more context
sudo nginx -t # for Nginx specifically: test the configNine times out of ten it is a config syntax error or a port already in use (ss -tulpn | grep :80 finds the culprit). Fix, then systemctl restart.
On a VPSPioneer managed VPS we write the unit files for your applications as part of setup, so a deploy is systemctl restart myapp and a crash is something the monitoring tells us about before you notice.