Dependencies and Targets
Scope: the two relationships between units — ordering ("after that") and requirement ("needs that") — and targets, the milestones they're all aimed at.
After is not Requires
The most-misread pair in systemd:
After=/Before=— pure ordering. "If both of us are starting, I go after it." It does not cause the other unit to start.Wants=/Requires=— requirement. "Starting me starts that too." With no ordering implied!- A real dependency is usually both:
Wants=(orRequires=) plusAfter=, on the same unit. The demo'sAfter=network.targetis ordering only: the system doesn't owe the service a network, it just sequences it after the network milestone.
Difference inside the family: Wants= is the forgiving
one — the wanted unit failing doesn't fail you.
Requires= is strict: if the required unit can't start,
yours doesn't either. Default to Wants= unless the
service is genuinely useless without the other.
Targets: named milestones
A target is a group unit: reaching it means starting everything that wants to be part of it. The landmarks:
| Target | Meaning |
|---|---|
network.target |
network stack is up (interfaces configured-ish) |
network-online.target |
network is actually online (stricter; services that need real connectivity order after this) |
multi-user.target |
the normal running system: all regular services, no GUI — "booted" for a server |
graphical.target |
multi-user + desktop |
timers.target |
where enabled timers attach |
WantedBy=multi-user.target in [Install] is thus the
service saying "I'm part of a normally booted system,"
and enable drops the symlink that proves it (you saw
it created in Chapter 3). systemctl get-default shows
which target boot aims for; systemctl isolate
<target> switches to one now (the runlevel-switch
equivalent).
The boot picture, when it's slow or broken
systemd-analyze critical-chain
systemd-analyze blame
critical-chain prints the chain of units that gated
the boot, with timings; blame ranks units by how long
their start took. (Documented usage — this guide's lab
didn't stage a slow boot to measure.) Between them they
answer "why did this box take four minutes to come up"
without folklore.
A dependency that isn't
Your service probably doesn't depend on other services
as often as instinct says. Two services both ordered
after network.target, with retries in the client, beat
a fragile web of Requires= that couples unrelated
failures together. Declare dependencies for things that
are truly prerequisites (a mount, a database the app
cannot start without) — and let ordinary network chatter
be ordinary.