systemd unit explainer
Paste a unit file or quadlet to get every key explained and its mistakes flagged.
Last updated
In short: To check a unit file, run systemd-analyze verify backup.service on the machine: it loads the file the way systemd does and prints every ignored key and refused setting. For podman quadlets, run /usr/libexec/podman/quadlet --dryrun (add --user for rootless files) to see the generated service or the reason it failed. This page does a similar check in your browser: paste the file and each key is explained, while typos, keys in the wrong section, bad time spans and cron-style OnCalendar values are flagged before you deploy.
Your input never leaves your browser. Everything is calculated on your device; nothing you type is sent to a server.
How does the systemd unit explainer work?
A unit file is a plain INI-style text file that tells systemd how to manage one thing: a service, a timer, a
socket, a mount or a watched path. It is split into sections such as [Unit], [Service]
and [Install], and each section only accepts its own keys. [Unit] holds the description,
dependencies and ordering, the type-specific section says what to run or when, and [Install] is only
read when you enable the unit.
systemd is forgiving in a way that hides mistakes. An unknown key, a key in the wrong section or a value it cannot
parse is skipped with a single warning in the journal, and the unit still loads with the default instead. Keys and
section names are case-sensitive, so execstart= is not ExecStart=. Podman quadlet files
(.container, .volume, .network, .pod, .kube,
.image, .build, .artifact) are stricter: one unsupported key in the quadlet section and the generator
refuses the whole file, so no service appears at all.
This checker parses the file the same way, looks every key up in a database built from the systemd 261 and podman 6
man pages (systemd.unit(5), systemd.service(5), systemd.exec(5),
systemd.timer(5) and podman-systemd.unit(5)), and checks booleans, time spans, file modes and
OnCalendar= expressions. It then applies rules that the parser alone does not catch, such as a timer
without a trigger or a quadlet with its own ExecStart=. On the real machine, confirm the result with
systemd-analyze verify for units and the quadlet generator's --dryrun mode for quadlets.
Worked examples
A cron schedule pasted into a timer
Input OnCalendar=0 3 * * * gives Error: cron syntax; write OnCalendar=*-*-* 03:00:00
systemd timers do not understand cron's five fields. systemd logs that it failed to parse the calendar specification, drops the line, and because the timer is then left without a trigger it refuses to load at all. The systemd form for 03:00 every day is *-*-* 03:00:00, or daily for midnight.
A typo that systemd silently ignores
Input Restart=on-faliure gives Error: did you mean on-failure?
systemd cannot parse the value, logs a warning that is easy to miss, and keeps the default Restart=no. The service loads and starts fine, but it will never be restarted after a crash. Misspelled key names behave the same way: the whole line is ignored.
A quadlet that never starts at boot
Input web.container without an [Install] section gives Note: add [Install] WantedBy=default.target
Quadlet generates web.service at every daemon-reload, and generated units cannot be enabled with systemctl enable. The [Install] section in the .container file is what makes the generator hook the service into default.target (rootless) or multi-user.target (rootful).
Frequently asked questions
How do I check if a systemd unit file is valid?
Run systemd-analyze verify /path/to/name.service. It parses the file like systemd does and prints unknown keys, values it cannot parse and settings that make systemd refuse the unit; no message about your file means it is clean. Add --user for user units. It also checks that the ExecStart= program exists, so run it on the machine that will use the unit.
Why is systemd ignoring a setting in my unit file?
Usually because of a typo in the key name, the wrong letter case, or a key in the wrong section, such as After= under [Service] instead of [Unit]. systemd skips such lines with only a warning in the journal. Run systemctl daemon-reload, then journalctl -b | grep your-unit to see the warning, or paste the file above.
How do I start a podman quadlet at boot?
Add an [Install] section with WantedBy=default.target to the .container file (multi-user.target for rootful quadlets), then run systemctl --user daemon-reload. Do not run systemctl enable: the service is generated, so enable fails. For rootless quadlets also run loginctl enable-linger once, so your user services start without a login.
What is the difference between Wants= and After= in systemd?
Wants= decides whether another unit is started; After= only decides the order. With Wants=b.service alone, both start in parallel. With After=b.service alone, b is not started at all. You usually need both, for example Wants=network-online.target plus After=network-online.target.
Why does my systemd timer not run?
Most often the timer was never enabled: it needs [Install] WantedBy=timers.target and systemctl enable --now name.timer. Other causes are a cron-style OnCalendar= line that systemd rejected, or a timer with only OnUnitActiveSec=, which never fires until the service has run once. systemctl list-timers shows the next run.
Is my unit file sent anywhere?
No. Parsing and checking run entirely in your browser; the text you paste is never transmitted or stored.