systemd
systemd is the service manager running as PID 1 on nearly every mainstream Linux distribution. It boots and supervises the system from declarative unit files, tracks processes with cgroup v2, and ships a large tool suite (systemctl, journalctl, systemd-analyze, and more).
The core reflex: query the installed system, don't guess
systemd's self-documentation is its strongest feature and the safest source of truth. Directive availability, defaults, and behavior drift across versions (roughly one major release every 6 months), so confirm against the running system rather than memory:
- What does directive X do?
man systemd.directivesis a reverse index mapping every directive to its man page. Look up the directive, then open the referenced page (e.g.RestartSec=tosystemd.service(5)). - What tools/pages exist?
man systemd.indexlists every systemd man page with a one-line description. - What is the effective config right now?
systemctl cat UNIT(on-disk file + all drop-ins),systemctl show UNIT(normalized runtime properties + state),systemd-analyze cat-config NAME(merged config files with compile-time defaults). - Which version am I on?
systemctl --version. Man pages tag features with "Added in version N"; match the host before recommending anything version-gated (run0 v256, soft-reboot v254, SysV-script removal v260). - Is systemd even present?
systemctl --versionorpidof systemd. A few distros (Devuan, Alpine default, containers) do not use it.
See references/self-documentation.md for the full introspection toolkit,
including busctl D-Bus queries and systemd-analyze verify/security.
Router: read the reference before acting
| Task | Reference |
|---|---|
Write/understand a unit file: types, [Unit]/[Install]/[Service]/[Socket] directives, dependencies (Requires=/Wants=/After=), templates foo@.service, specifiers, file locations, precedence, drop-ins |
references/units.md |
Drive units and read logs: systemctl verbs, journalctl filtering, systemd-analyze, the full tool inventory |
references/commands.md |
Schedule work: .timer units, OnCalendar=/OnBootSec=, Persistent=, cron replacement, user timers |
references/timers.md |
Harden a service: ProtectSystem=, PrivateTmp=, NoNewPrivileges=, DynamicUser=, SystemCallFilter=, RestrictAddressFamilies=, scoring with systemd-analyze security |
references/security.md |
Limit resources: cgroup v2, MemoryMax=/MemoryHigh=, CPUQuota=/CPUWeight=, IOWeight=, TasksMax=, slices |
references/resource-control.md |
Query systemd for help / introspect the live manager: man systemd.directives, systemctl show/cat, systemd-analyze verify, busctl |
references/self-documentation.md |
| Subsystems: journald, logind, networkd/resolved/timesyncd, udev, credentials, sysext, portable services, homed, oomd, coredump | references/subsystems.md |
Non-negotiable rules
- Always
systemctl daemon-reloadafter editing any unit file (or the manager keeps the stale copy).systemctl editreloads for you. - Prefer drop-ins over editing vendor files.
systemctl edit UNITcreates/etc/systemd/system/UNIT.d/override.conf; a package update then cannot clobber your change.systemctl edit --fullforks the whole file;systemctl revert UNITundoes overrides. enable!=start.enablesets boot-time autostart via the[Install]section;startruns it now. Useenable --nowfor both.WantedBy=/RequiredBy=only take effect afterenable.- Ordering and requirement are orthogonal.
Requires=pulls a unit in but does not order it; addAfter=for ordering. This pair is the single most common real-world mistake. - Validate before shipping.
systemd-analyze verify ./unit.servicelints for unknown keys/sections and missing deps. For timers,systemd-analyze calendar "SPEC"confirms the next elapse. - Precedence:
/etc>/run>/usr/lib. Admin overrides beat runtime beat vendor.systemd-deltashows what is overridden.
Troubleshooting loop
systemctl status UNIT: active/failed state, recent log tail, PID, cgroup.journalctl -u UNIT -b: this-boot logs; add-e(jump to end),-f(follow),-p err(errors only),--since "10 min ago".systemctl cat UNIT: see the effective file + drop-ins you are actually running.systemctl show UNIT -p PROPfor one normalized property.- Fix the file,
systemctl daemon-reload,systemctl restart UNIT. - Recurring restarts: check
Restart=,RestartSec=, andStartLimitIntervalSec=/StartLimitBurst=(a unit that trips the start limit stays down untilsystemctl reset-failed UNIT).
Gotchas
Type=simple(the default whenExecStart=is set) considers the service "started" the instant it forks, before the program is ready. UseType=notify(withsd_notify()) orType=exec/Type=forking+ readiness for correct ordering. AvoidType=forkingfor new services.Type=oneshotneedsRemainAfterExit=yesto show as active after the command exits (common for setup/config units).- A leading
-on anExecStart=line ignores its failure (ExecStartPre=-/bin/rm ...). Onlyoneshotallows multipleExecStart=. DynamicUser=yesimpliesProtectSystem=strict,PrivateTmp=yes,ProtectHome=read-only, andRemoveIPC=, so state must live underStateDirectory=//var/lib/<name>, not an arbitrary path.systemd-tmpfiles --purgeis dangerous (historically could delete/homebefore the v256.1 fix). Treat destructive maintenance commands with care.- Do not blanket-set
NoNewPrivileges=yeson a unit that relies on a setuid helper (e.g.ping,sudo); it breaks the privilege gain.