iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

systemd Services

systemd is the init system on most Linux distros. It owns service lifecycle, logging, sockets, timers (cron replacement), resource limits, and dependency ordering. Writing a proper unit file beats a hand-rolled init script or screen+ssh — your service comes back after reboot, restarts on crash, and its logs land in journald automatically.

A production-shaped systemd service + timer

EXAMPLE
# 1) /etc/systemd/system/shop-api.service
[Unit]
Description=Shop API server
After=network-online.target postgresql.service
Wants=network-online.target

[Service]
Type=exec
User=shop
Group=shop
WorkingDirectory=/srv/shop-api/current
EnvironmentFile=/etc/shop-api.env             # KEY=VALUE per line; not exposed to logs
ExecStart=/usr/bin/node dist/server.js
ExecReload=/bin/kill -HUP $MAINPID
Restart=on-failure
RestartSec=5s
TimeoutStopSec=20s
SuccessExitStatus=0 143                       # 143 = SIGTERM

# Resource limits + hardening
LimitNOFILE=65535
MemoryHigh=512M
MemoryMax=768M
CPUQuota=200%
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/srv/shop-api/cache
PrivateTmp=true
PrivateDevices=true

# Logs go to journald automatically
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

# 2) Apply changes
sudo systemctl daemon-reload
sudo systemctl enable --now shop-api
sudo systemctl status shop-api
sudo journalctl -u shop-api -f -n 200

# 3) Reload config without dropping connections
sudo systemctl reload shop-api

# 4) Timer (cron replacement) — runs the same unit on a schedule
# /etc/systemd/system/shop-backup.service
# [Service]
# Type=oneshot
# ExecStart=/usr/local/bin/shop-backup.sh

# /etc/systemd/system/shop-backup.timer
# [Unit]
# Description=Nightly DB backup
# [Timer]
# OnCalendar=*-*-* 02:30:00          # every day at 02:30
# Persistent=true                    # run on next boot if missed (laptop, sleep)
# RandomizedDelaySec=10m             # avoid herding when many hosts share a cron
# [Install]
# WantedBy=timers.target

sudo systemctl enable --now shop-backup.timer
sudo systemctl list-timers --all

# 5) Useful introspection
systemctl cat   shop-api          # show the unit file as systemd sees it
systemctl edit  shop-api          # drop-in override (NEVER hand-edit /etc/systemd)
systemctl show  shop-api -p ActiveState -p SubState -p MemoryCurrent
journalctl -u   shop-api --since='1 hour ago' --output=json-pretty | jq .

# 6) Reboot resilience — does this come up cleanly?
sudo reboot
# After reboot, systemctl status should show 'active (running)'.

Why it matters

NoNewPrivileges + ProtectSystem=strict + PrivateTmp + a non-root User give you a meaningful security baseline for almost no work. They prevent a compromised service from writing outside its expected paths, escalating privileges, or sharing temp files with anything else on the host — and they cost nothing to flip on.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
sudo systemctl status nginx
sudo systemctl restart nginx
sudo journalctl -u nginx -f
Try it Yourself »

Discussion

Loading…