Almost all of the day-to-day work you do with systemd comes down to about thirty commands. The rest of the man page is for the day something is genuinely strange.
The systemd(1) and journalctl(1) man pages are thorough and almost unusable under pressure. When a service is down at 02:00, or a supervisor asks you to reconstruct what a host was doing during an incident window, you do not want to be reading option tables. You want the invocation. This is the set I actually reach for, grouped by the task in front of me rather than by the tool, tested on systemd 255. Copy it, keep it somewhere you can find it, and stop re-deriving the same five journalctl flags every week.
Service lifecycle: start, enable, mask, reload
The distinction that trips people up is start versus enable. start runs the unit now; enable wires it to boot. They are independent, which is why enable --now exists — do both in one go. mask is the heavier hammer: it symlinks the unit to /dev/null so nothing, not even a dependency, can start it until you unmask.
Free · 4 minutes
Is your engineering team shipping safely, or quietly accumulating risk?
Fourteen questions on how work gets from idea to production — cadence, testing, rollback, and the key-person risk in your delivery. Banded finding on screen, full sheet by email.
# run / stop / restart now
systemctl start nginx
systemctl stop nginx
systemctl restart nginx
# reload config without dropping connections (if the unit supports it)
systemctl reload nginx
systemctl reload-or-restart nginx # reload if possible, else restart
# boot-time wiring
systemctl enable nginx
systemctl enable --now nginx # enable AND start
systemctl disable --now nginx # disable AND stop
# hard-off: nothing can start it until unmasked
systemctl mask nginx
systemctl unmask nginx
# re-read unit files after editing them on disk
systemctl daemon-reload
The one people forget is the last: after you change a unit file on disk, systemd is still running the old definition until daemon-reload. If a change “isn’t taking”, that is nearly always why.
Seeing what is running and what has failed
Two questions cover most triage: is this one unit healthy, and what across the whole system is broken? status answers the first and helpfully prints the last few log lines. --failed answers the second in one line and is the first thing worth typing on a host you have just been handed.
# one unit, with recent log tail
systemctl status nginx
# scriptable checks (exit code 0/non-zero)
systemctl is-active nginx
systemctl is-enabled nginx
systemctl is-failed nginx
# the whole system
systemctl --failed # everything in a failed state
systemctl list-units --type=service # running/loaded services
systemctl list-unit-files --state=enabled # what will start at boot
systemctl list-dependencies nginx # what this unit pulls in
The is-* checks return proper exit codes, so they belong in health probes and deployment scripts, not just at the prompt — the same discipline that makes a pre-commit baseline worth having: a machine-checkable answer beats eyeballing output.
Reading a unit’s real configuration
Do not guess what a unit is configured to do — ask it. systemctl cat prints the unit file plus every drop-in override, in load order, so you see the effective source. systemctl show prints the fully resolved properties as systemd actually holds them, which is where you confirm the real value of a setting after overrides have been applied.
# the unit file + all drop-ins, in order
systemctl cat nginx
# every resolved property, or just the ones you want
systemctl show nginx
systemctl show nginx -p MemoryCurrent -p ActiveState -p ExecStart
# where the drop-ins live: /etc/systemd/system/nginx.service.d/
If someone asks “why is this service capped at 512MB”, systemctl show nginx -p MemoryMax gives you the answer with no ambiguity, and cat tells you which file set it.
journalctl: follow, filter, export
This is the half of the cheat-sheet you will use most. The four filters that matter are unit (-u), time (--since / --until), priority (-p) and boot (-b). Combine them freely. -f follows live; -e jumps to the end; -n limits the count.
# by unit
journalctl -u nginx
journalctl -u nginx -f # follow live
journalctl -u nginx -e # jump to newest
journalctl -u nginx -n 100 # last 100 lines
# by time window (great for incident reconstruction)
journalctl -u nginx --since "2026-09-08 09:00" --until "2026-09-08 10:00"
journalctl --since "1 hour ago"
# by severity: emerg,alert,crit,err,warning,notice,info,debug
journalctl -u nginx -p err # err and worse
# by boot, plus kernel ring buffer
journalctl -b # this boot
journalctl -b -1 # previous boot
journalctl --list-boots
journalctl -k # kernel messages this boot
# search text across the journal
journalctl -u nginx --grep "timeout"
# export and hand off
journalctl -u nginx -o json > nginx-logs.json
journalctl -u nginx -o cat # message text only, no metadata
The time-window query is the one that earns its keep during an incident. When you are working out mean time to recovery — one of the DORA Four delivery metrics — a precise --since/--until against the affected unit reconstructs the sequence far faster than scrolling. And the journal has housekeeping of its own:
journalctl --disk-usage # how much the journal is holding
journalctl --vacuum-time=7d # drop entries older than 7 days
journalctl --vacuum-size=500M # cap the journal at 500M
journalctl --verify # check journal integrity
Boot time, and editing units without breaking them
When a machine boots slowly, systemd-analyze tells you where the time went. blame ranks units by initialisation time; critical-chain shows the dependency path that actually gated boot — the slow unit and the slow chain are not always the same thing.
systemd-analyze # total boot time
systemd-analyze blame # slowest units, ranked
systemd-analyze critical-chain # the path that gated boot
Finally, editing. Never hand-edit a packaged unit file in /usr/lib/systemd/system/ — a package update will overwrite it. Use systemctl edit, which creates a drop-in override that survives upgrades and layers cleanly on top of the vendor file.
# create a drop-in override (survives package updates)
systemctl edit nginx
# edit a full copy of the unit instead of a drop-in
systemctl edit --full nginx
# throw away your local changes, back to the vendor default
systemctl revert nginx
systemctl edit runs daemon-reload for you when you save, so the change is live immediately — one less step to forget. If an override ever makes things worse, systemctl revert puts you back to the packaged definition in one command, which is exactly the safety net you want when you are changing a service you do not fully own.
None of this is obscure. It is the small, stable core of systemd that carries the overwhelming majority of real operational work — and the reason to have it to hand is that the moment you need it is never the moment to be reading the man page.
Build and rescue work
Hands-on delivery of this kind is handled by Sixteen Pillars Studio.
Free interactive tool
Website compliance checklist
What your site has to do, based on what it actually does
Answer as much or as little as you like — the list builds as you go. Nothing is stored against your name and no email is required.
Everything that applies
Ordered by what to do first: legal requirements you can close quickly, then larger pieces of work, then what is expected rather than required. Not exhaustive, and not a legal audit.
Dated PDF, yours to keep or circulate.
Most technology problems are not technology problems. They are control problems.
The systems exist. The investment has been made. The question is whether leadership can understand, direct, evidence, and sustain what those systems produce. Find out where control exists — and where it only appears to.