Innovate | Connect | Transform
ContactService statusUSD $

GICT knowledge base

Understanding Runlevels and Systemd Boot Targets in Linux

Published

LinuxLinux and Commands

If you spend enough time working with Linux, you’ll notice something interesting: no matter which flavor you use, the boot process is both familiar and full of surprises. Sometimes your system boots straight to a text login, other times you’re welcomed by a graphical desktop. When things go wrong, maybe you end up in “single-user mode” or “rescue mode.” If you’ve ever wondered how Linux decides what to start at boot or how to control what comes up, and in what order you’re in the right place.

The answer lies in two key concepts: runlevels (from the old SysVinit days) and systemd boot targets (the modern approach). Understanding these is essential for any Linux admin, developer, or power user. Not only does it help you troubleshoot boot issues, but it also lets you fine-tune your environment for servers, desktops, or anything in between.

In this guide, we’ll take a deep dive into runlevels and systemd targets: what they are, how they evolved, and how you can use them to control your system’s behavior. We’ll look at practical commands, real-world scenarios, and some lessons learned from years of managing Linux systems. Whether you’re a beginner or just need a refresher, you’ll walk away with both the “how” and the “why” of this foundational Linux topic.

The History: Where Runlevels Come From

Let’s start with a bit of history because understanding where runlevels came from makes it much easier to appreciate systemd targets.

The SysVinit Legacy

In the early days of Linux, most distributions used a system called SysVinit to manage the boot process and services. When your computer powered on, SysVinit started the kernel, which then ran a special process called init (with process ID 1). The job of init was to launch all the background services (daemons), mount filesystems, and eventually bring the system to a usable state.

To organize all these tasks, SysVinit used runlevels each one representing a different state of the system. Think of runlevels as “modes” your system could be in, each with its own set of running services.

Here’s a classic mapping of runlevels:

Runlevel Name Typical Purpose
0 Halt Shutdown
1 Single-user Maintenance (root only, minimal services)
2 Multi-user Multi-user, no network (Debian/Ubuntu)
3 Multi-user Multi-user, network (no GUI)
4 Undefined User definable (rarely used)
5 Graphical Multi-user, network, GUI (X11)
6 Reboot Reboot

How Did It Work?

On boot, SysVinit read /etc/inittab to determine the default runlevel. Then it started or stopped services based on scripts in /etc/rcN.d/ (where N was the runlevel number). For example:

  • Runlevel 3: Start network, SSH, and all multi-user services, but not a graphical desktop.
  • Runlevel 5: Start everything in runlevel 3, plus the graphical login manager.

You could change runlevels on the fly (e.g., init 3 or telinit 1) handy for troubleshooting.

Why Did We Move On? The Limits of Runlevels

SysVinit and runlevels worked, but they weren’t perfect:

  • Rigid Structure: Only seven runlevels, and only one could be active at a time.
  • No Parallelization: Services started one after another, making boot slow.
  • Poor Dependency Management: Couldn’t easily express “only start X after Y and Z.”
  • Limited Flexibility: Custom runlevels were rare and awkward.
  • No Standardization: Different distros used runlevels differently (e.g., Debian’s runlevel 2 was multi-user with networking, while on Red Hat, it was single-user).

As Linux systems became more complex and faster boot times became important (especially for desktops and servers), something better was needed.

Enter systemd: The Modern Way

Systemd is now the default init system for nearly all major Linux distributions: Fedora, Ubuntu, Debian, CentOS, openSUSE, Arch, and more. It’s a controversial topic among old-school admins, but there’s no denying it’s here to stay.

What Is systemd?

At its core, systemd is a suite of tools that manages the whole boot process, services (called “units”), logging, device handling, and more. It starts the system, brings up services in parallel (for speed), and can manage dependencies and state better than SysVinit ever could.

Boot Targets: The New “Runlevels”

Instead of runlevels, systemd uses targets. Targets are unit files that group services and dependencies together so they’re like runlevels, but much more flexible.

Some common targets:

Target Name Purpose (Roughly) Equivalent Runlevel
rescue.target Single-user mode for maintenance Runlevel 1
multi-user.target Multi-user, network, text login Runlevel 3
graphical.target Multi-user, with graphical desktop (GUI) Runlevel 5
reboot.target Reboot the system Runlevel 6
poweroff.target Shut down the system Runlevel 0
emergency.target Minimal rescue shell (even less than rescue) N/A

But here’s the key: you can define your own targets, add dependencies, and have multiple targets “active” at once.

The Anatomy of a systemd Boot

Let’s walk through what actually happens when you boot a modern Linux system with systemd:

  • Firmware (BIOS/UEFI) Loads the Kernel: The bootloader hands control to the Linux kernel.
  • Kernel Starts systemd: The kernel launches process 1, which is now /sbin/init (a symlink to systemd).
  • systemd Reads Default Target: The default target is usually graphical.target or multi-user.target, as specified in /etc/systemd/system/default.target.
  • systemd Resolves Dependencies: systemd figures out which services, mounts, and other units are needed for this target.
  • Parallel Startup: systemd starts all units as fast as possible but respects dependencies.
  • Login Prompt or Desktop: When the target is reached, you get your login prompt (text or graphical).

Mapping Runlevels to systemd Targets

Most systemd-based distros still support the old runlevel commands for compatibility. Here’s how the mapping works:

Runlevel SysV Meanings systemd Target
0 Halt poweroff.target
1 Single-user rescue.target
2, 3, 4 Multi-user multi-user.target
5 Graphical graphical.target
6 Reboot reboot.target

For example, if you run init 3 or telinit 3 on a modern system, systemd interprets that as multi-user.target.

How to Check and Change Boot Targets

1. View the Current Target

systemctl get-default

This tells you what target your system boots into by default (e.g., graphical.target or multi-user.target).

2. List All Targets

systemctl list-units --type=target

This shows all targets currently active.

3. Change the Default Boot Target

To set your system to boot to a text login (no GUI):

sudo systemctl set-default multi-user.target

To switch back to graphical boot:

sudo systemctl set-default graphical.target

4. Switch Targets on the Fly

If you’re at a text login and want to start the GUI:

sudo systemctl isolate graphical.target

If you want to go back to text mode:

sudo systemctl isolate multi-user.target

The isolate command transitions the system to the specified target, stopping services not needed for the new target and starting any additional ones.

Practical Scenarios & Use Cases

Scenario 1: Troubleshooting a Broken Desktop

Suppose you update your system and suddenly the graphical desktop won’t start. Maybe it crashes or you get a black screen. To troubleshoot:

  • Boot the system.
  • At the GRUB menu, edit the boot parameters and add systemd.unit=multi-user.target to boot into text mode.
  • Log in at the console and check logs, drivers, or try reinstalling GUI components.
  • Once fixed, return to graphical.target.

Scenario 2: Running a Headless Server

For servers, you almost never need a graphical desktop. Set the default target to save resources:

sudo systemctl set-default multi-user.target

Your server will boot to a fast, text-only login.

Scenario 3: Single-User or Rescue Mode

If your system can’t mount a disk or you break /etc/fstab, boot into rescue mode:

  • At the GRUB menu, press e to edit the boot line.
  • Add systemd.unit=rescue.target or systemd.unit=emergency.target.
  • The system boots into a root shell with minimal services.

How Targets Work Behind the Scenes

A target is just a special kind of systemd unit file (a .target file) that groups other units together. You’ll find these in /usr/lib/systemd/system/ or /etc/systemd/system/.

For example, multi-user.target might “require” networking, SSH, and cron, but not the graphical display manager. graphical.target “requires” everything in multi-user.target, plus your X11 display manager.

You can see what services are part of a target:

systemctl list-dependencies multi-user.target
systemctl list-dependencies graphical.target

want to see what runs at boot? Try:

systemctl list-dependencies default.target

Customizing and Creating Your Own Targets

One of systemd’s strengths is that you can create your own targets perfect for custom server roles or special maintenance modes.

Suppose you want a special “maintenance” target that boots into text mode, but only starts a few key services. You could:

  1. Copy multi-user.target to a new name in /etc/systemd/system/maintenance.target.
  2. Edit the .target file to “require” only the services you want.
  3. Set it as your default with systemctl set-default maintenance.target.

Most users won’t need custom targets, but it’s a power tool for complex setups.

Advanced: systemd Rescue and Emergency Modes

  • rescue.target: Like “single-user mode” in SysVinit. Root shell, minimal services.
  • emergency.target: Even more minimal. Just a root shell, no filesystems mounted except /. Use if you’ve really broken something crucial.

To boot into these, edit your boot line in GRUB (press e), and add:

systemd.unit=rescue.target

or

systemd.unit=emergency.target

These modes are essential for disaster recovery, editing broken configs, or fixing disk issues.

The Role of runlevels and Compatibility

You might still see the runlevel command it prints the previous and current runlevel, for compatibility. On systemd systems, it’s really just a wrapper that maps targets to runlevels.

Try:

runlevel

You’ll get something like N 5 (N means “none before,” 5 is the current runlevel, i.e., graphical.target).

You can still use telinit 3 or init 5 and systemd will translate it, but it’s better to use systemctl commands for clarity.

Real-World Lessons: Mistakes, Pitfalls, and Tips

  • Don’t Set the Boot Target Lightly: Changing the default target affects every boot. If you switch to multi-user.target and then forget, you might be surprised next time your server boots without a GUI.
  • Be Careful with isolate: systemctl isolate stops services not in the new target. If you have custom services or dependencies, test carefully.
  • Document Custom Targets: If you create or change targets, document what you’re doing future you and your teammates will thank you.
  • Use the Logs: If the system doesn’t reach the expected target, check the logs:
    journalctl -b

    This shows all messages from the current boot.

  • Know How to Recover: If you break the boot process (e.g., by misconfiguring a target or a service), boot into rescue.target or from a live USB, fix the files, and reboot.

FAQ

Are runlevels still used?
Not really. They’re supported for compatibility, but systemd targets are far more flexible.

Can I have multiple targets active at once?
Yes. Unlike runlevels, systemd can have multiple targets “active,” as targets are just groupings of units.

What’s the difference between rescue and emergency target?
Rescue has basic services and a root shell; emergency is the most minimal mode possible.

How do I see which services a target will start?
Use systemctl list-dependencies <target>.

How do I permanently set my system to boot without a GUI?
sudo systemctl set-default multi-user.target

Wrapping Up: Why This Still Matters

Even though most of us don’t edit /etc/inittab anymore, the concepts behind runlevels and systemd targets are still central to how Linux boots and runs. Mastering these lets you:

  • Troubleshoot faster when something goes wrong
  • Optimize boot times and resource usage
  • Build reliable, flexible servers and desktops
  • Recover from system failures with confidence

Whether you’re a server admin, a desktop power user, or just someone who likes to know how things work under the hood, understanding Linux boot targets is time well spent.

Conclusion

Linux has come a long way from the days of rigid runlevels and slow, sequential boots. While systemd isn’t perfect (and yes, it has its critics), it gives administrators and users more control and flexibility than ever before. Learning to work with systemd’s targets not just fighting against them makes you a better troubleshooter, a more confident admin, and someone who’s prepared for whatever your next Linux adventure throws at you.

So, next time you see your system dropping into a text login, or you need to recover from a rough update, remember: it’s all about targets. And now, you know exactly what to do.

Related guides

Account services are unavailable until the production backend is configured.