systemd target

On this page 7

A systemd target is a special systemd unit, with a name ending in .target, that groups other units and represents a synchronization point or a desired system state during Linux boot and operation. Targets such as multi-user.target and graphical.target tell systemd which services, mounts and sockets must be active, and they replace the numbered runlevels of the older SysVinit system.

A target contains no program of its own. Its whole meaning comes from dependencies and ordering: other units declare that they are wanted by a target, and the target pulls them in when it is activated. This makes targets the backbone of system initialization in systemd-based distributions.

How targets organize the boot process

At boot, systemd activates the default target, usually a symbolic link named default.target that points to graphical.target on desktops or multi-user.target on servers. Systemd then walks the dependency graph backward and starts every unit the target requires, in parallel wherever ordering constraints allow.

Two separate kinds of relationship are involved. Requirement dependencies such as Wants= and Requires= decide which units are pulled into the transaction. Ordering dependencies such as After= and Before= decide the sequence. A common misunderstanding is that Wants= implies order; it does not, so a unit that must start after the network needs both statements.

DirectiveEffectStrength
Wants=Starts the listed unit as wellWeak: failure does not stop the target
Requires=Starts the unit and fails if it failsStrong
After= / Before=Defines start order onlyOrdering, not activation
WantedBy=Install hint creating a .wants link on enableWeak, set in the [Install] section
Conflicts=Stops the listed unit when this one startsMutual exclusion
Dependency directives used with targets

When an administrator runs systemctl enable, systemd reads the [Install] section and creates a symbolic link in a directory such as /etc/systemd/system/multi-user.target.wants/. That link is what makes the service start with the target.

Standard targets and their runlevel equivalents

systemd ships a set of well-known targets with defined meanings. Some correspond to classic runlevels, and compatibility aliases such as runlevel3.target still exist for older tools and habits.

TargetSysVinit runlevelSystem state
poweroff.target0System shuts down
rescue.target1Single-user mode with basic system, root shell
multi-user.target2, 3, 4Full multi-user system without a graphical login
graphical.target5Multi-user system with a display manager
reboot.target6System restarts
emergency.targetNo direct equivalentMinimal shell, root filesystem often read-only
Main system targets

Beyond these, many targets serve as internal synchronization points: sysinit.target for early system setup, basic.target for the basic boot environment, local-fs.target for mounted local filesystems, network-online.target for a configured network, and timers.target for activating a systemd timer at boot. Passive targets such as network.target only mark a point in the ordering and are not meant to be pulled in by ordinary services.

Targets compared with runlevels

Targets generalize the runlevel idea, but the differences are significant. Runlevels were mutually exclusive numbered states executed by sequential scripts; targets are composable groups in a dependency graph, and several can be active at the same time.

AspectSysVinit runlevelssystemd targets
NamingNumbers 0 to 6Descriptive names ending in .target
Active at onceExactly oneMany, nested by dependencies
Startup orderScript numbering such as S20 or K80Dependency and ordering graph
ParallelismMostly sequentialParallel by default
Custom statesLimited and distribution-specificAny number of user-defined targets
Runlevels and systemd targets

Other init systems take different paths. OpenRC keeps named runlevels with dependency-based scripts, while SysVinit still runs on a few distributions that avoid systemd entirely.

Working with targets in practice

Administrators interact with targets through systemctl and, at boot, through the kernel command line. The most common operations are short commands that every Linux administrator should know.

  • Show the default: systemctl get-default prints the target used at boot.
  • Change the default: systemctl set-default multi-user.target makes a server boot without a graphical session.
  • Switch now: systemctl isolate rescue.target stops everything not required by the new target.
  • Boot once into a target: add systemd.unit=rescue.target or emergency to the kernel command line in GRUB or systemd-boot.
  • Inspect members: systemctl list-dependencies graphical.target shows the tree of pulled-in units.

Custom targets are useful for application stacks. A file such as app-stack.target with a description, plus services declaring WantedBy=app-stack.target, lets an administrator start or stop an entire group with one command. Only targets with AllowIsolate=yes can be used with isolate, which protects against switching into states that would leave the system unusable.

Common pitfalls with targets

Problems with targets usually come from misunderstood dependencies rather than from systemd itself.

The classic error is ordering a service after network.target and expecting the network to be configured; only network-online.target, pulled in with Wants=, waits for configured connectivity, and it can slow boot. Running systemctl isolate over SSH into a target that stops networking cuts off the remote session. Finally, dependency loops between custom units cause systemd to delete a job from the transaction to break the cycle, which appears in journalctl as an ordering cycle warning and can leave a service silently not started.

Another frequent mistake is editing vendor unit files under /usr/lib/systemd/system to change which target a service belongs to. Package updates overwrite those files, so changes belong in drop-in overrides created with systemctl edit or in copies under /etc/systemd/system. After any change to unit files, systemctl daemon-reload is required before systemd recognizes the new dependency graph, and systemd-analyze critical-chain helps verify which units actually delay reaching a target.

The idea in brief

A systemd target is like a checklist for a particular mode of the computer. The checklist named everyday server mode lists all the services that must run; the one named desktop mode adds the graphical login screen.

When the computer starts, it picks one checklist and makes sure everything on it is running, starting as many items at the same time as possible. Switching to a different checklist, such as repair mode, stops whatever the new mode does not need.

A practical scenario

An operations team manages virtual machines that were installed from a desktop image and therefore boot into graphical.target, wasting memory on a display manager nobody uses. The team runs systemctl set-default multi-user.target through its configuration management tool, and after the next reboot each machine saves several hundred megabytes of memory and starts faster.

Later, a VM fails to boot after a disk was removed from /etc/fstab incorrectly. Using the virtualization console, an engineer edits the kernel command line in GRUB to add systemd.unit=emergency.target, gets a minimal root shell, fixes the fstab entry and reboots normally. Knowing the targets turns a potential rebuild into a ten-minute repair.