Table of Contents
Understanding Boot Targets
Boot targets in a systemd based Linux system define what the machine should look like after boot. They describe which services and system components must be started or stopped to reach a particular operating state, such as a graphical desktop, a multi user text console, or a minimal rescue environment.
A boot target is a systemd unit with the type target. It groups other units, usually services and sometimes other targets, into a named state. When you tell systemd to switch to a target, it starts everything that target wants and stops whatever is no longer needed, so the machine transitions to a new mode of operation.
Targets replaced the classic SysV runlevels concept. Instead of opaque numeric runlevels like 3 or 5, you now have descriptive names such as multi-user.target and graphical.target, and you can define your own targets for custom scenarios.
A boot target is a systemd unit of type target that represents a particular operating state of the system by grouping multiple units together.
Standard Targets and Their Roles
On most Linux distributions that use systemd, you will encounter a set of standard boot targets. Each one describes a typical operating mode.
The basic multi user text mode is provided by multi-user.target. This target gives you a networked system with multiple login consoles but no graphical desktop. It is broadly equivalent to the traditional SysV runlevel 3 on many distributions. Servers often operate in this mode.
The graphical desktop mode is provided by graphical.target. This builds on multi-user.target and additionally pulls in a display manager and graphical session. It roughly corresponds to runlevel 5 in older systems. Desktop distributions normally choose this as the default boot target.
For early initialization work there is basic.target, which ensures that fundamental services like file system mounting, device setup, and basic logging are in place. It is not normally used directly by administrators to control the overall boot state, but many other targets depend on it.
The rescue environment is represented by rescue.target. This gives you a single user environment with minimal services, usually a root shell on the console and only the components needed for basic troubleshooting. It is similar to the classic single user mode. From here you can fix configuration errors that prevent a normal boot.
For situations where the system is broken more severely, there is emergency.target. This is an even more minimal environment that skips most system initialization. You are dropped into a root shell with the root filesystem typically mounted read only. You use this target when essential system services or filesystems are so damaged that even rescue mode cannot start safely.
In addition to these operational targets there are also power related targets such as poweroff.target, reboot.target, and halt.target. These targets coordinate the steps needed to shut down or restart the system cleanly.
Default Boot Target
The default boot target is the target that systemd attempts to reach when the system starts normally. It is defined by the default.target unit, which is a symbolic link to another target file.
On most desktop systems, default.target points to graphical.target. On many servers, it points to multi-user.target. You can inspect where it points with a single command. For example, use:
systemctl get-default
This tells you the name of the target that the system reaches after a normal boot. Changing the default does not immediately switch the current state, but it affects the next reboot.
To set a new default boot target, use:
sudo systemctl set-default multi-user.target
This creates or updates the symlink default.target under the systemd unit directory so that future boots will aim for the new target. To switch back to a graphical default later, you would run:
sudo systemctl set-default graphical.target
The default boot target is controlled by default.target, which is a symlink. Use systemctl get-default to see it and systemctl set-default NAME.target to change it.
Inspecting Targets
Before changing targets it is useful to understand what a given target actually does. Systemd gives you several ways to inspect targets and their relationships.
To list all known targets on the system, whether active or not, you can run:
systemctl list-units --type=target --all
This shows you every target unit, its current state, and a brief description. From this you can discover targets that your distribution defines in addition to the standard ones, such as special rescue or maintenance modes.
To see what a specific target wants to start, you can inspect its dependencies. For example, to examine graphical.target use:
systemctl show -p Wants graphical.target
This prints the units that graphical.target pulls in when started. You can also examine the targets that it requires or is wanted by, using different properties. For a more readable tree style overview of the active system state, use:
systemctl list-dependencies graphical.target
This presents a hierarchical view of the units pulled in by the target. It helps you understand how a change to one target might affect others, since targets frequently depend on or include each other.
If you want details such as documentation references, description, and dependencies for a single target you can use:
systemctl status multi-user.target
Although typically used for services, systemctl status can also show useful information for targets, including whether they are active and what they require.
Switching Between Targets
Switching between targets allows you to change the system’s operating mode without a full power cycle. This is especially useful for troubleshooting or for moving between graphical and non graphical modes.
To switch immediately to a different target and stop units that are not part of it, use:
sudo systemctl isolate NAME.target
For example, to switch from a graphical session to a purely text based multi user mode, use:
sudo systemctl isolate multi-user.target
This command stops the graphical display manager and related units that are not required by multi-user.target. Your existing login on a text console continues to work, but graphical sessions are terminated.
Similarly, to switch back to a graphical environment from multi user mode, you would use:
sudo systemctl isolate graphical.target
This starts the display manager and required graphical services. Again, services that are not part of the new target are stopped, which means isolating a target can significantly change which daemons are running.
Isolating rescue.target is another common operation. When you run:
sudo systemctl isolate rescue.target
the system transitions into single user rescue mode. Non essential services are stopped and you are typically prompted on the console for the root password, depending on your distribution’s policy.
Changing the default boot target with systemctl set-default does not immediately isolate that target. If you want both an immediate switch and a persistent default you must run both commands separately.
systemctl isolate NAME.target switches the current system mode to that target and stops units not required by it. Use it carefully, because active sessions or services can be terminated.
Rescue and Emergency Boot Targets
Rescue and emergency targets are crucial for system recovery when normal booting fails or produces an unusable system.
The rescue.target brings the system into a single user environment with minimal, but more complete, initialization than emergency.target. Networking might or might not be up, depending on distribution policies, but system filesystems are usually mounted. This environment is designed for tasks like fixing broken configuration files, undoing recent changes that prevent multi user operation, or repairing services that fail to start.
The emergency.target provides an even more basic environment. It is usually invoked when the system cannot mount filesystems correctly or when core dependencies required by normal boot are missing or damaged. In emergency mode only the bare minimum is done, often just mounting the root filesystem and starting a root shell. Services such as networking, logging, and most daemons are not started.
You can reach these modes in two main ways. First, from a running system using systemctl isolate rescue.target or systemctl isolate emergency.target. Second, through the boot loader by editing kernel command line parameters.
Typical distributions let you append systemd.unit=rescue.target or systemd.unit=emergency.target to the kernel command line at boot time. This instructs systemd to start directly into the corresponding mode instead of the default target. This can be vital when the system cannot reach the default target at all.
While in rescue or emergency mode you often need to remount the root filesystem read write before editing configuration files. For example, you might run:
mount -o remount,rw /
once you have a root shell. After repairing the system you can attempt to switch back to a higher target with systemctl isolate multi-user.target or simply reboot.
Because these modes grant you direct root access with minimal protections, they are also a security consideration. Physical access to a machine often implies the ability to boot into such modes and bypass certain access controls.
Custom Targets
In addition to the standard targets provided by your distribution, you can create custom targets that define your own system modes. This is useful when you need repeatable environments that start a particular set of services and stop others.
A custom target is defined by a unit file of type target. For example, you might create /etc/systemd/system/maintenance.target with content similar to the following:
[Unit]
Description=Maintenance mode
[Install]
WantedBy=multi-user.target
This example defines a minimal target that you can later extend by telling other services to start when it is reached. You then link specific services to this target using Wants or RequiredBy relationships in those services’ unit files or with drop-in configuration files.
For instance, suppose you want an environment where only your backup daemons and an SSH server are running. You add appropriate WantedBy=maintenance.target lines to those service units or provide corresponding snippets. When you isolate maintenance.target using:
sudo systemctl isolate maintenance.target
systemd stops services not needed by it and starts only those that belong to the target, giving you a controlled maintenance state.
If you want to switch to this target automatically on some occasions you can also make it a parent or child of other targets. For example, by making maintenance.target want multi-user.target, you can create a mode that includes everything in multi-user.target plus some extra components that you only need for routine maintenance.
You can also make a custom target the default boot target using systemctl set-default maintenance.target if your use case requires that the system normally boots into a specialized mode. This is less common on general purpose systems but can be appropriate for appliances or dedicated servers.
Whenever you define a new target or modify unit relationships it is important to reload systemd’s configuration with:
sudo systemctl daemon-reload
so that the changes take effect. Targets are a flexible mechanism, so you can model complex boot and operating modes, but that flexibility also means you should test your custom targets carefully before relying on them in production.
Summary of Boot Targets in Daily Use
In practical day to day administration you typically interact with a few main targets. You check or change the default boot target with systemctl get-default and systemctl set-default. You switch between text and graphical modes with systemctl isolate multi-user.target and systemctl isolate graphical.target. You use systemctl isolate rescue.target or the systemd.unit= kernel parameter for recovery scenarios, and you may occasionally use emergency.target for very low level repairs. When you need special modes tailored to your environment you define custom targets and relate your own services to them.
Boot targets give you a structured and explicit way to control how your Linux system behaves at boot time and at runtime, without relying on obscure numeric runlevels.