A tiny, but perfect guide of installing WSL 2 as a server on Windows Server 2022
Tags: windows, server, wsl, linux
Published: 2022-06-08 11:20:26

Yay! WSL 2 now supports on Windows Server 2022!
and, Microsoft now introduced how to install WSL 2 on Windows Server 2022!

[WSL2 now available on Windows Server 2022](https://techcommunity.microsoft.com/t5/itops-talk-blog/wsl2-now-available-on-windows-server-2022/ba-p/3447570)

TL;DR; for normal users:
1. Install Windows update [KB5014021](https://support.microsoft.com/topic/may-24-2022-kb5014021-os-build-20348-740-preview-2b180bd4-dceb-4c49-b8cf-402b342ebc84?WT.mc_id=modinfra-68298-pierrer) first. you can skip if you installed this update.
2. Install Hyper-V if not installed.
3. just run `wsl --install` and see process of install kernel, default distro like Ubuntu, and done.

Well, are you still having trouble? okay, I tell you how to figure it out.

## Cannot apply WSL version 2?

YOU MUST INSTALL [KB5014021](https://support.microsoft.com/topic/may-24-2022-kb5014021-os-build-20348-740-preview-2b180bd4-dceb-4c49-b8cf-402b342ebc84?WT.mc_id=modinfra-68298-pierrer) UPDATE FIRST!

## `wsl --install` does not work!

If you run `wsl --install`, some users will see HOWTO message instead of installing message.
Me too. but don't worry. you can go manual solution for installing WSL 2 like Windows 10. note that if you see not working via `wsl --install`, you'll see not working via `wsl --update` too. so, follow instructions below:

1. run `wsl --set-default-version 2`.
2. Download [WSL Update Package](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi)
3. Install and Reboot
4. `wsl --install -d Ubuntu` to install WSL Distro. You can change distro by `wsl -l -o` for list of Available distros.
5. WSL2 will initialized automatically.

## WSL 2 didn't run and got message `WslRegisterDistribution failed with error: 0x800706be`.

when you install Windows Server, you'll never see create user while installing and startup as `Administrators`.
`Administrator` is Windows root user and CANNOT use some specified features on Windows(such as Microsoft store apps, WSL2...). so, you must create a normal user with `Administrator`, `Users` group. `Administrator` group makes you can initialize distros and manage WSL status. yes, it also activates annoying privileges elevation popup like Windows 10.

after login a created user and run distros like Ubuntu, you'll see just working without problem.

## Is this not Windows 11 based?

Sadly, NO. so you can't use WSL with Windows 11 only feature like these:

- attach Hyper-V Private network and set static IP.
- Startup script.
- WSLg.

## I want to make SSH server open to external network.

You can follow [this instructions](https://www.hanselman.com/blog/how-to-ssh-into-wsl2-on-windows-10-from-an-external-machine).
Yes. [he posted more easier solution](https://www.hanselman.com/blog/the-easy-way-how-to-ssh-into-bash-and-wsl2-on-windows-10-from-an-external-machine) but it can use only SSH solutions, not for other linux service.

If you scripted solution and attach in Task scheduler, I made and recommend powershell script below:

{% gist https://gist.github.com/composite/003e27c68b70325a049caff2b32c2ea8 %}

NOTE: `sudo` will prompt password by default. if you don't want to do without password, use `sudo visudo` and append a line like:
```sh
# change username to your linux default user name who can run sudo.
username ALL=(ALL:ALL) NOPASSWD: /sbin/service, /usr/sbin/service
```
or you can just use `NOPASSWORD: ALL` instead for all sudo process without prompt password.

save to file with path you want, and make new task schedule with:

- Input task name as you want.
- User is current WSL's user.
- Check **Run whether user is logged on or not** and **Run with the highest privileges**.
- Trigger: schedule every 5 mins recommended. if first run or IP changed, this script will register port forwarding and firewall inbound and outbound rules. or replace if exists.
- Action: `%WINDIR%\system32\\WindowsPowerShell\v1.0\powershell.exe`
- Arguments: `-NoProfile -NoLogo -NonInteractive -ExecutionPolicy Bypass -File "C:\Path\To\wsl2-network.ps1`
- Working Directory: it's optional. but you can input ps1 path.

Run it now! Next, how you can check it's success:

- `wsl hostname -I` for see current distro's IP. (may be 1 or multiple IPs. but if it dosen't work, check default distro and set default distro and run script again.)
- `netsh interface portproxy show v4tov4` for list of port forwaing. and see IPs equal to `wsl hostname -I`.
- Open Windows advanced firewall and see `WSL 2 Firewall Unlock` exists in inbound and outbound rules.

At last, go to external client and connect SSH and see it works.
Don't forget enable `PubkeyAuthentication yes` or `PasswordAuthentication yes` in distro's `/etc/ssh/sshd_config` and check the SSH service is running or `wsl service ssh start`.
If you connected your WSL2 SSH Server, it's done.

## How to connect Windows RDP by tunneling WSL instead of Direct?

Yes, sure, RDP shouldn't connect without any security tunnel.
First, Disable ALL RDP-In inbound rules in Windows Firewall. You can skip if your server's network is in router.
and you must get distro's gateway IP first.

```sh
$ ip route show | grep -i 'default via'| awk '{print $3 }'
```

If you wan't tunneling hostname instead of IP, you can make crontab script with the script:

```sh
#!/bin/bash

IP=$(ip route show | grep -i 'default via'| awk '{print $3 }')
HOST="gateway"

if cat /etc/hosts | fgrep -q "$HOST"
        then sed -i "/$HOST/ s/.*/$IP\t$HOST/g" /etc/hosts
        else echo >> /etc/hosts; echo "$IP\t$HOST" >> /etc/hosts; echo >> /etc/hosts
fi
```

because WSL is always change `/etc/hosts` for localhost forwarding. but you can disable by follow instructions in `/etc/hosts` file.

Anyway, login as root via `sudo -i` and `crontab -e` for edit crontab file:

```sh
*/5 * * * * /root/gatehost.sh
```

and you must also run `wsl sudo service cron start` in Windows startup if you are using auto port forwarding powershell script by me, you don't need it.

and connect SSH with tunneling such as:

```sh
ssh -N -L33389:gateway:3389 wsluser@external.wsl.host
```

and connect IP via `localhost:33389` and see it works.

Once you followed these instructions, you are ready to serve with WSL, and serve with docker service, etc.
You know that's not recommended for production use. it's for workstation or development server. right?

For production, use Linux with Hyper-V, cloud or native instead. WSL is more extremely slow and unstable than Hyper-V, you know.

Happy Windows-ing!