Skip to content

Systemd Units: Unit, Service, Target, Start vs Enable

Mental model

A unit file declares what to manage. Start/stop controls runtime. Enable/disable controls boot. Wants/requires declare dependencies. After/before declare ordering. These are orthogonal axes.

What it looks like

"Enable the service" — expecting it to start immediately.

What it really is

Unit file: a declarative INI-style config in /etc/systemd/system/ or /usr/lib/systemd/system/. Tells systemd what a thing is and how to manage it. Every managed object is a unit.

Unit types: - service — a process (ExecStart, restart policy, resource limits) - target — a synchronization point grouping other units (like a runlevel) - timer — triggers a service on a schedule (replaces cron) - socket — socket activation (start service on connection) - mount — manages a mount point - path, slice, scope, swap — other managed objects

start/stop: changes runtime state now. Transient. Lost on reboot unless the unit is enabled.

enable/disable: creates or removes a symlink in a target's .wants/ directory. Controls whether the unit starts at boot. Does NOT affect current runtime state.

wants: weak dependency. "Start X if possible, but don't fail me if X fails." Creates a .wants/ symlink.

requires: hard dependency. "X must succeed or fail me too."

after/before: ordering directives. "Start me after X is started." No dependency implied — if X isn't otherwise pulled in, after alone won't start it.

Why it seems confusing

  • enable does NOT start the service. start does NOT enable it.
  • wants does NOT imply ordering. after does NOT imply dependency.
  • These are two orthogonal axes: dependency (wants/requires) and ordering (after/before). You usually need both.

What actually matters

  • systemctl enable --now foo = enable + start in one command.
  • Wants= + After= is the common pattern: depend on it AND order after it.
  • Requires= without After= starts both in parallel — the dependent unit may start before its requirement is ready.
  • Targets group units. multi-user.target is roughly "system ready for non-graphical use." Enabling a service usually symlinks it into multi-user.target.wants/.

Common mistakes

  • Running systemctl enable foo and wondering why it's not running yet (need start or --now).
  • Using Requires= without After= and getting a race condition.
  • Using Wants= thinking it guarantees ordering (it doesn't).
  • Editing unit files without running systemctl daemon-reload.
  • Confusing systemctl restart (stop+start) with systemctl reload (send SIGHUP, re-read config without stopping).

Small examples

Enable vs start:

systemctl enable nginx       # symlink created, starts on next boot
systemctl status nginx       # inactive (dead) — not started yet
systemctl start nginx        # running now, but won't survive reboot
systemctl enable --now nginx # both: symlink + start immediately

Wants vs requires:

# Unit A wants B (weak):
# If B fails to start, A starts anyway.

# Unit A requires B (hard):
# If B fails to start, A is not started.

# Neither implies ordering. Add After=B.service for sequencing.

Checking unit relationships:

systemctl list-dependencies nginx.service
systemctl show nginx.service -p Wants,Requires,After

One-line summary

Units declare what to manage; start/enable are orthogonal; wants/requires and after/before are orthogonal.