83

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?

9
  • 4
    The systemctl command won't work on WSL without some serious hacking. Not recommended.
    – user535733
    Dec 6, 2021 at 0:49
  • Why would you want to use systemctl on Windows 11? You should be using Windows commands. What are you trying to achieve? Dec 6, 2021 at 1:04
  • 3
    @WinEunuuchs2Unix The OP is running Ubuntu in WSL2. The question is not about running systemctl in Windows but in Ubuntu. That said user535733 is absolutely right. Dec 6, 2021 at 1:06
  • 2
    Try using the service command instead.
    – user535733
    Dec 6, 2021 at 1:26
  • 2
    Specifically, sudo service ssh restart. But be aware that ssh doesn't quite work as you might expect under WSL2 either. Dec 6, 2021 at 1:52

2 Answers 2

103

Surprisingly, after 6 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.

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 problem may be that:

  • Your release of WSL doesn't support Systemd. In this case, there are multiple workarounds available. See the Alternatives to Systemd in WSL section below.

  • The good news is that Systemd is now officially supported in Ubuntu on many WSL systems. See below for how to determine if your system supports it and how to enable it (if you need it).

Should you enable Systemd in WSL?

First, consider whether you should enable Systemd in WSL. Enabling Systemd will automatically start a lot of background services and tasks that you really may not need under WSL. As a result, it will also increase WSL startup times, although the impact will be dependent on your system. Check the Alternatives section below to see if there may be a better option that fits your needs. For example, the service command may do what you need without any additional effort.

While I'm happy that Systemd is available as an option, I personally plan on continuing to run without it whenever possible.

How to enable Systemd in Ubuntu/WSL

As background, there are now two different "delivery mechanisms" (I'll think of a better term, hopefully) for WSL2. I'd call them different "versions" or "releases", but we tend to already use that term for WSL version 1 and 2.

  • Originally, WSL1 and WSL2 both came as a Windows feature, which was enabled through the Turn Windows features on or off settings. This feature was (and still is) built-in to Windows, and is called the "in-box" version of WSL.

  • In October of 2021, Microsoft started making WSL2 available as a Windows application, which could be installed through the Microsoft Store (and other methods described below).

It's the WSL application that supports Systemd. Currently, the in-box version of WSL does not support Systemd. To use the new WSL application, you must be on a supported Windows release:

  • New WSL users with Windows 11 22H2 or later will automatically receive the application version of WSL when running wsl --install, unless specifically adding the --inbox option.

  • Windows 11 21H2 users can still install the WSL application using the methods below.

  • Windows 10 users will need KB5020030 or later. Note that it is not yet clear at the time of this update whether older Windows 10 releases will work. I have personally only been able to validate it on Windows 10 22H2 so far.

With the prerequisite Windows version in place, you can then install or upgrade to the 1.0.0 release (or later) of the WSL application using several methods:

  • Through the Microsoft Store (as "Windows Subsystem for Linux").

  • Or from the Releases page in the Github repo. To install a release manually:

    1. Reboot (to make sure that WSL is not in use at all). A simple wsl --shutdown may work, but often will not.

    2. Download the 1.0.0 (or later) release from the link above.

    3. Start an Administrator PowerShell and:

      Add-AppxPackage <path.to>/Microsoft.WSL_1.0.0.0_x64_ARM64.msixbundle
      wsl --version # to confirm
      

To enable, start your Ubuntu (or other Systemd) distribution under WSL (typically just wsl ~ will work).

sudo -e /etc/wsl.conf

Add the following:

[boot]
systemd=true

Exit Ubuntu and again:

wsl --shutdown

Then restart Ubuntu.

sudo systemctl status

... should show your Systemd services.


Alternatives to Systemd in WSL

systemctl is most often used to start services under Ubuntu. For older releases that don't support Systemd, there are still several alternatives that might work in place of the systemctl command.

Fortunately, Ubuntu is pretty good overall about being able to cope without Systemd.

How to handle the lack of Systemd

Systemd at its core is just a (probably gross-oversimplification) "way of accomplishing system tasks". There is usually (but not always, see footnote below) 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: Docker

    Many packages/services are available as Docker images. Docker runs great under Ubuntu on WSL2 (specifically WSL2; it will not run on WSL1). If there's not a SysVinit "service" script for the service you are trying to start, there may very well be a Docker image available that runs in a containerized environment.

    Example: Elasticsearch, as in this question and my answer.

    • Bonus #1: Doesn't interfere with other packages already installed (no dependency issues).
    • Bonus #2: The Docker images themselves pretty much never use Systemd, so you can often inspect the Dockerfile to see how the service is started without Systemd. For more information see the next option - "The manual way."
  • Option 3: "The 'manual' way"

    Edit: Bumped down notch from its former position as "Option 2", since Docker is probably a better alternative for many services.

    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 4: Run Systemd as PID 1 in a PID namespace/container

    Finally, it's possible to get Systemd running under WSL2 (but not WSL1). This is a fairly advanced topic, although there are multiple scripts and projects that attempt to simplify it.

    Warnings: Systemd fundamentally changes many aspects of Ubuntu when started, including the way that X sockets, login, WSL Interop, temp files, and more! Due to the shared VM nature of WSL2, some of these changes can even impact other distributions you are using without Systemd.

    My personal recommendation is to either (a) make sure that you understand what is going on behind the scenes should you use one of these techniques, (b) don't do it!, or (c) at the very least, when asking questions about why something doesn't work, make sure to let people know that you are using a Systemd helper script under WSL (and which one).

    With that out of the way ...

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

    I don't personally run any of them on a regular basis, 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:

    1. 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.

    2. 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.

    3. And after proving to yourself that it's possible, I recommend exiting all WSL instances completely, then doing wsl --shutdown. 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.

Footnote 1 - Snap

There are certain applications and function in Ubuntu that are just so complex that they are unlikely to ever be disentangled from Systemd. The most obvious example here would be the Snap system. I'm sure it's theoretically possible that a version of the Snap system could be created without the use of Systemd. However, there are two good reasons why this won't happen (anytime soon, at least):

  • Snap is a system created and supported by Canonical.

  • Canonical has selected Systemd as the Ubuntu init system. Just because WSL doesn't support it (easily) doesn't change this. Canonical developers wrote the Snap system with the expectation that the functionality of Systemd is present.

  • There currently doesn't seem to be any third-party desire to port Snap to non-Systemd distributions. Those distributions typically utilize Flatpak in place of Snap. It should be noted, however, that even Flatpak tends to utilize Systemd on distributions where it is available. However, Flatpak is also available for non-Systemd distros.

Footnote 2 - Gnome

Gnome is also an application (ecosystem) that is very tightly coupled with Systemd, but it's popular enough that there have been ports to non-Systemd init systems. That said, running it on Ubuntu does assume the presence of Systemd, so you would have to reverse-engineer the process used on those other distributions if you wanted to run it on Ubuntu/WSL without the use of Systemd.

Footnote 3 - Other Systemd-dependent applications

There are also cases where certain software expects Systemd and just won't work (or at least not fully) if it isn't present. One that I came across recently is Cockpit.

While I was able to get it up and running without Systemd, it ultimately expects Systemd to be present in order to execute many, if not most, functions. In effect, parts of Cockpit are a front-end to Systemd.

This type of software, one that executes Systemd commands (such as systemctl), may be the exception to the "there's an alternative" rule.

8
  • 2
    A good question, and a good answer, so plus one. I thought that service cmd belongs to systemd. I have on wsl the error from the OP, but mariadb works with service.service is a wrapper and can be used with init.d and systemctl.
    – Timo
    Mar 10 at 9:57
  • I'm confused. WSL used to have systemctl/d, WSL used to work fine with mounted drives, WSL used to be a very solid representation of Ubuntu... now I'd call it Winbuntu as it seems its no longer ubuntu but windows version of it corrupted to fit in WSL... which is strange, because I remember when WSL 1 came out I was able to install TRUE ubuntu on it without issue through powershell instead of the windows store. What happened to WSL? Is there any way to get true ubuntu back?
    – gunslingor
    Jul 19 at 13:35
  • @gunslingor I agree ... you're confused ;-). But seriously, you are almost certainly remembering this incorrectly (or perhaps nostalgically). WSL has never had Systemd support. Here's the Github issue on the topic, opened just 15 days after the first WSL1 beta was made available. Jul 19 at 15:38
  • A related comment in that issue, "running WSL without cron or syslog or sshd or a terminal emulator (what we have got is sort of a console emulator) and other servers/daemons/background tasks, is not the same as running an Ubuntu developer machine", shows that people didn't considered it "real Ubuntu" even back then. WSL has made great progress over the years since then, but it's still a developer tool on Windows, not a virtual machine designed to replicate a "full Ubuntu (or other Linux) environment." Jul 19 at 15:39
  • Yeah, hyperV is probably what i was remembering, pure ubuntu image. I suspect WSL is using some component of that pretweaked and routed to the host system to serve itself easier... or lxssmanager or something, i forget. Docker seems to run better in wsl ubuntu than as docker destop using wsl and then you also have very slow ubuntu when using a mounted windows share, but fast ubuntu and win when using a mounted ubuntu share... why I suspect its hyperV really... I remember this issue.
    – gunslingor
    Jul 20 at 21:01
6

Ok, my answer may not be related to the question, but I had a similar issue. I wanted to startup an Nginx with "sudo systemctl start nginx", but it didn't work on Ubuntu WSL. But I figured out that the command "sudo service nginx start" does exactly the same thing. It can startup Nginx without calling "systemctl"

3
  • 2
    Right - I cover using the service command to do this in my existing answer. Please see the section titled, "The old way". Jul 11 at 2:31
  • @NotTheDr01ds You're right. I'm sorry. I missed that point.
    – Anynomius
    Jul 12 at 19:56
  • It works, sudo service docker start Oct 21 at 9:40

Not the answer you're looking for? Browse other questions tagged or ask your own question.