Units, dependencies & targets
How systemd orders and wires the system.
systemd is far more than a service starter — it is the manager that models the whole system as a graph of units with dependencies, and understanding that graph is what lets you reason about boot order, failures, and cleanups. A unit is any managed thing: a .service (a process), a .socket (a listening socket), a .timer (a schedule), a .mount, a .target (a grouping/milestone). Each declares how it relates to others, and systemd computes the order.
$ systemctl list-units --type=service # running services$ systemctl cat nginx.service # the actual unit definition$ systemctl show nginx -p After -p Requires # what it is ordered after / needsAfter=network.target ...Requires=...
Ordering vs requirement
Two independent relationships trip people up. Ordering (After=, Before=) says when a unit starts relative to another — but not whether it needs it. Requirement (Requires=, Wants=) says whether starting this unit should pull in another — but not in what order. You usually want both: a web app is After=postgresql AND Wants=postgresql, so the database is started and started first. Wants is the softer form (pull it in, but do not fail if it fails); Requires is strict. Getting these right is how you express real service dependencies.
[Unit]Description=My AppWants=postgresql.service # pull in the DB (soft: do not fail if it does)After=postgresql.service network-online.target # ...and start after it[Service]ExecStart=/usr/local/bin/myappRestart=on-failure
Targets: milestones, not runlevels
Targets replace the old SysV runlevels with named grouping units — multi-user.target (a normal server), graphical.target (with a GUI), rescue.target (single-user recovery). A target is just a well-known synchronization point that pulls in a set of units; "boot to multi-user" means "reach that target," which means "start everything wanted by it." You can list what a target pulls in, and switch targets at runtime, which is how you drop to rescue mode or bring the system to a known state.
$ systemctl get-defaultmulti-user.target # what the system boots to$ systemctl list-dependencies multi-user.target | head # what it pulls in$ sudo systemctl isolate rescue.target # switch to single-user recovery now