systemd Basics: Start, Stop, Enable and Read Logs with journalctl

The systemctl commands that manage services on modern Linux, how to start a service at boot, write a unit for your own app, and read logs with journalctl.

Published
Reading time
3 min

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

bash
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 boot

enable --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

bash
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 crashed

The 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:

bash
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

bash
journalctl --disk-usage
sudo journalctl --vacuum-time=30d      # drop entries older than 30 days

Make 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:

ini
[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.target

Then:

bash
sudo systemctl daemon-reload            # after creating or editing any unit
sudo systemctl enable --now myapp
sudo systemctl status myapp
sudo journalctl -u myapp -f

Restart=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

bash
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 config

Nine 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.

#linux#systemd#systemctl#journalctl#services

Keep reading

More from Linux

All guides

Linux

How to Set Up SSH Keys and Turn Off Password Login

Generate an ed25519 key on Mac, Linux or Windows, install it on the server, test it, and disable password authentication so brute-force attacks cannot succeed.

3 min read →

Linux

How to Create a Sudo User and Disable Root SSH Login

Create a user with sudo rights on Ubuntu, Debian, AlmaLinux or Rocky, test it, then lock root out of SSH without locking yourself out.

3 min read →

Linux

20 Linux Commands Every Server Admin Uses Daily

The commands that cover 95% of real server work — logs, resources, services, files and finding what is wrong — each with the flags worth knowing.

3 min read →