System has not been booted with systemd as init system (PID 1). Can't operate

I use WSL2 on Windows 11. I want to run the systemctl command in Ubuntu 20.04, but it gives me the following error:

System has not been booted with systemd as init system (PID 1). Can't operate. Failed to connect to bus: Host is down

How can I fix it?


Solution 1:

Surprisingly, after 5 years or so of WSL, there doesn't seem to be a good, general-purpose "Systemd" question here on Ask Ubuntu. So this looks like a good one to use for that purpose.

The problem

In general, when you see either of the following two messages:

  • System has not been booted with systemd as init system (PID 1). Can't operate.
  • Failed to connect to bus: Host is down

Then it's typically the same root cause. In the case of systemctl and attempting to start ssh, you are seeing both.

The core problem, as mention in the comments, is that WSL doesn't use Systemd, even in distributions where it is the default. Instead, WSL currently uses its own /init process as PID 1, which performs a few WSL-specific tasks that I mention in this answer (so I won't repeat them here).

And while WSL is (IMHO) a great way to have a full-featured Linux CLI in Windows (and recently, even GUI), the lack of Systemd does tend to make things more difficult in distributions that expect it to be there. Fortunately, Ubuntu is pretty good overall about being able to cope without Systemd.

How to handle the lack of Systemd

And regardless, Systemd at its core is just a (probably gross-oversimplification) "way of accomplishing system tasks". There is (usually? always?) a way of doing the same task without Systemd, and often more than one way.

  • Option 1: "The old way"

    In Ubuntu on WSL, many of the common system services still have the "old" init.d scripts available to be used in place of systemctl with Systemd units. You can see these by using ls /etc/init.d/.

    So, for example, you can start ssh with sudo service ssh start, and it will run the /etc/init.d/ssh script with the start argument.

    Even some non-default packages such as MySql/MariaDB will install both the Systemd unit files and the old init.d scripts, so you can still use the service command for them as well.

  • Option 2: "The 'manual' way"

    But some services don't have a init-script equivalent, especially on other distributions. For simplicity, let's assume that the ssh init.d script wasn't available.

    In this case, the "answer" is to figure out what the Systemd unit files are doing and attempt to replicate that manually. This can vary widely in complexity. But I'd start with looking at the Systemd unit file that you are trying to run:

    less /lib/systemd/system/ssh.service
    
    # Trimmed
    [Service]
    EnvironmentFile=-/etc/default/ssh
    ExecStartPre=/usr/sbin/sshd -t
    ExecStart=/usr/sbin/sshd -D $SSHD_OPTS
    RuntimeDirectory=sshd
    RuntimeDirectoryMode=0755
    

    I've trimmed out some of the less relevant lines for understanding its behavior, but you can man systemd.exec, man systemd.service, and others to see what most of the options do.

    In this case, when you sudo systemctl start ssh, it:

    • Reads environment variables (the $SSHD_OPTS) from /etc/default/ssh
    • Tests the config, exits if there is a failure
    • Makes sure the RuntimeDirectory exists with the specified permissions. This translates to /run/sshd (from man systemd.exec). This also removes the runtime directory when you stop the service.
    • Runs /usr/sbin/sshd with options

    So, if you don't have any environment-based config, you could just set up a script to:

    • Make sure the runtime directory exists. Note that, since it is in /run, which is a tmpfs mount, it will be deleted after every restart of the WSL instance.
    • Set the permissions to 0755
    • Start /usr/sbin/sshd as root

    ... And you would have done the same thing manually without Systemd.

    Again, this is probably the simplest example. You might have much more to work through for more complex tasks.

  • Option 3: Run Systemd as PID 1 in a PID namespace/container

    Finally, it's possible to get Systemd running under WSL. This is a fairly advanced topic, although there are multiple scripts and projects that attempt to simplify it. Even so, my personal recommendation is to make sure that you understand what is going on behind the scenes should you use one of these techniques.

    Let's start with some of the more popular projects to enable Systemd in WSL:

    • Genie
    • WSL2-Hacks
    • Distrod

    I haven't personally run any of them, but all are open-source, and I've scanned the source to compare the techniques. At the core, each creates a new namespace or container where Systemd can run as PID 1.

    You can see this in action by following the steps:

    • Run:

      sudo -b unshare --pid --fork --mount-proc /lib/systemd/systemd --system-unit=basic.target
      

      This starts Systemd in a new namespace with its own PID mapping. Inside that namespace, Systemd will be PID1 (as it must, to function) and own all other processes. However, the "real" PID mapping still exists outside that namespace.

      Note that this is a "bare minimum" command-line for starting Systemd. It will not have support for, at least:

      • Windows Interop (the ability to run Windows .exe)
      • The Windows PATH (which isn't necessary without Windows Interop anyway)

      The scripts and projects listed above do extra work to get these things working as well.

      Wait a few seconds for Systemd to start up, then:

      sudo -E nsenter --all -t $(pgrep -xo systemd) runuser -P -l $USER -c "exec $SHELL"
      

      This enters the namespace, and you can now use ps -efH to see that systemd is running as PID 1 in that namespace.

      At this point, you should be able to run systemctl.

      And after proving to yourself that it's possible, I recommend exiting the WSL instance completely, then doing wsl --terminate <distro> on it. Otherwise, you will have some things be "broken" until you do. They can likely be "fixed", but that's beyond the scope of any one Ask Ubuntu question ;-). My recommendation is to refer to the projects above to see how they handle it.