# WSL2

{% hint style="info" %}
It is possible to have multiple distributions on WSL.
{% endhint %}

## Installing WSL

{% embed url="<https://github.com/codeedu/wsl2-docker-quickstart>" %}

```bash
# As administrator
# If the flag `--no-distribution` is not specified, Ubuntu will be automatically installed
wsl --install
```

After reboot, updates are applied, and the terminal is automatically started to continue Ubuntu installation on WSL.

It will ask you to setup your Unix user and password.

If everything went well running `wsl` in terminal will open the connection to Ubuntu.

### Installing more instances

#### Import the image

Download the `tar.gz` or `.gz` file of a [wsl ubuntu image](https://ubuntu.com/desktop/wsl).

Then create a folder where the new instance will be used, and run the command to import it.

```bash
wsl --import <distribution-name> <installation-folder> <wsl2-tar-file-path>
```

Where:

* `<distribution-name>`: Is the name you want to give this new Linux instance.
* `<installation-folder>`: Is the folder you want to install the new Linux instance.
* `<wsl2-tar-file-path>`: Is the path to the downloaded `.tar.gz` file.

```bash
wsl --import ubuntu-another "C:\Ubuntu-Another" "C:\downloaded\ubuntu-jammy-wsl-amd64-wsl.rootfs.tar.gz"
```

After the import verify the installation:

```bash
wsl -l -v
```

{% hint style="warning" %}
Imported distributions will log as `root` user. Manually create another user.
{% endhint %}

Bring up the instance with `wsl -d <distro-name>`.

#### Setup new user

```bash
useradd -m -G sudo -s /bin/bash "<username>"
passwd "<username>"
```

Set this user as the default login user by creating or editing `/etc/wsl.conf`.

```
[user]
default=<username>
```

#### Setup instance hostname

Also add to the `/etc/wsl.conf` a new hostname so that the instance's hostname reflect the distro name.

```
[network]
hostname = <distro-name>
generateHosts = false
```

After update the `/etc/hosts` and add the new hostname with `127.0.0.1`.

```
...
127.0.0.1    <distro-name>
...
```

#### Update & Upgrade

After, shutdown the instance with `wsl --terminate <distro-name>`. Log with the created user and finish the installation with:

```bash
sudo apt update
sudo apt upgrade
```

#### Add new terminal to Windows terminals

Create a new terminal to automatically open the new instance, with the following command line:

{% code title="Command Line" %}

```
C:\Windows\system32\wsl.exe -d <distro-name>
```

{% endcode %}

## Using WSL

{% hint style="warning" %}
When using your WSL, do **NOT** run things on `/mnt/c/*` because it will lose performance.
{% endhint %}

Accessing Windows files from inside Linux is possible by accessing from `/mnt/c`.

On Windows the Linux filesystem is basically a network folder as `\\wsl$`.

### Commands

<table><thead><tr><th width="288">Command</th><th>Description</th></tr></thead><tbody><tr><td><code>wsl</code></td><td>Start the default distribution.</td></tr><tr><td><code>wsl -l -v</code></td><td>List all distributions with detailed information.</td></tr><tr><td><code>wsl --shutdown</code></td><td>Shutdown ALL distributions.</td></tr><tr><td><code>wsl -d &#x3C;distro-name></code></td><td>Connect to a specific distribution, in case you have more than one.</td></tr><tr><td><code>wsl --terminate &#x3C;distro-name></code></td><td>Shutdown specific distribution.</td></tr><tr><td><code>wsl --manage &#x3C;distro-name> --move &#x3C;new-location></code></td><td>Move the distribution to a new location.</td></tr><tr><td><code>wsl --set-default &#x3C;distro-name></code></td><td>Sets the distribution as the default.<br><em>Will have a</em> <code>*</code> <em>beside their name.</em></td></tr><tr><td><code>wsl --unregister &#x3C;distro-name></code></td><td>Unregisters the distribution and deletes the root filesystem.</td></tr><tr><td><code>wsl --help</code></td><td>Show all wsl options and arguments.</td></tr></tbody></table>

## Configuring WSL

### `.wslconfig` vs `wsl.conf`

{% embed url="<https://learn.microsoft.com/en-us/windows/wsl/wsl-config#main-wsl-settings>" %}
WSL config options
{% endembed %}

The `.wslconfig` is a global configuration file that applies configuration to ALL the distros.

* This file is not automatically created.
* Must be placed to your Windows User root folder. (`%UserProfile%` or `C:\Users\<UserName>`)
* WSL will detect the existence of this file every time it is initiated. *If the file is incorrect, WSL will initiate without the specified configurations.*

If you want to setup configurations for specific distros then use the `wsl.conf` file.

* You will place this file in `/etc` folder of the desired distribution. (`/etc/wsl.conf`)

### Auto size reduction of `.vhdx` file

The WSL2 virtual disk is a `vhdx` file that grows as you use your linux distro. If you exclude files, the disk will not shrink automatically. (**`vhdx` always grows**)

#### Install Optimize-VHD

In a elevated Powershell run:

```bash
Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V-Management-PowerShell -All
```

This will install the Optimze-VHD feature without having to install the whole Hyper-V module and dependencies.

#### Configure --set-sparse in distro

{% hint style="info" %}
Not sure why to configure this if it will have to be disabled before running `Optimize-VHD`.
{% endhint %}

For virtual disks that already exist convert them with:

```bash
wsl --shutdown
wsl --manage <distro-name> --set-sparse true [--allow-unsafe]
```

#### To manually reduce the vhdx size

To reduce the distro vhdx size ([source](https://superuser.com/questions/1827953/reclaim-wsl2-disk-space-after-setting-it-to-sparse/1834374#1834374)), you must manually run:

```bash
wsl --shutdown
wsl --manage <distro-name> --set-sparse false
Optimize-VHD -Path "<path-to-distro>\ext4.vhdx" -Mode Full
wsl --manage <distro-name> --set-sparse true [--allow-unsafe]
```

#### Other untested ways (wslcompact)

If even after that the disk size does not decrease, you can manually shrink with this third-party tool.

{% embed url="<https://github.com/okibcn/wslcompact>" %}
wslcompact
{% endembed %}

```bash
wslcompact -c <distro-name>
```

### Limiting WSL resource consumption

{% code title=".wslconfig or wsl.conf" %}

```properties
[wsl2]
memory=4GB
processors=4
swap=1GB
```

{% endcode %}

{% hint style="info" %}
After changes on this file don't forget to `wsl --terminal <distro-name>`.
{% endhint %}

### Configure .bashrc

#### Show current git branch in terminal

{% code title=".bashrc" %}

```bash
# Show current git branch in terminal
parse_git_branch() {
   git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\[\033[33m\]$(parse_git_branch)\[\033[00m\]\$ '
```

{% endcode %}

### Configure Hostname

Configure the WSL instance hostname to reflect the `<distro-name>` given. This will make easier to identify which instance is running in the terminal, and it is not supposed to have any impact.

See here how to configure [#setup-instance-hostname](#setup-instance-hostname "mention").

## Setup as your Dev space

Your code project would stay inside Linux, but you will code from Windows.

{% hint style="success" %}
Before openning projects inside WSL in VSCode, make sure you have the `Remote Development` plugin installed in VSCode.
{% endhint %}

## Backing up & Restore WSL

#### `.vhdx` file

You can find the `.vhdx` file, which is the virtual machine hard drive file here:

```
%LocalAppData%\Packages\CanonicalGroupLimited.Ubuntu_79rhkp1fndgsc\LocalState
```

You could save this entire file to backup the entire Linux.

If you format your computer, on your new install:

* Install wsl again.
* Configure same user and password (maybe not needed).
* Shutdown the Linux virtual machine.
* Substitute the `.vhdx` file with the backup one.
