Linux on Windows
Tags: productivity, windows, wsl, terminal
Published: 2020-09-27 12:40:56


#Linux On Windows

## :question: Abstract

Not So Basic: Devenv is a series of tutorials in which we aim to have a nice, productive and portable development environment that takes the best of both worlds between Linux and Windows.

In this first tutorial "Linux On Windows" we do the groundwork to install:
 - WSL 2: an efficient system to install Linux distributions on your PC. Thus giving access to a Unix shell.
 - Docker Desktop: for local development environment, to avoid system-dependent configuration.
 - Windows Terminal: a productive, configurable and efficient terminal that plays well with WSL, multiple profiles and shells.

## :memo: Overview

To complete this tutorial, you need to:

- [Upgrade to Windows version 2004](#upgrade-to-windows-version-2004)
- [Enable WSL 2](#enable-wsl-2)
- [Install a Linux distribution](#install-a-linux-distribution)
- [Install Docker Desktop](#install-docker-desktop)
- [Install Windows Terminal](#install-windows-terminal)

## Upgrade to Windows version 2004

:warning: This step can take a long time (2h+) depending on your machine and connection. **Do not attempt this if you have limited time.**

Run `winver` to check Windows version.

If your Windows version is lower than 2004, go to `Settings > Update & Security` to update your system[^check-for-updates]. Repeat this step until your PC restarts with the right version[^already-have-docker-desktop].

## Enable WSL 2

Following [Microsoft documentation](https://docs.microsoft.com/nl-nl/windows/wsl/wsl2-kernel), you need to **enable the Windows Subsystem for Linux** [(Step 1)](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-1---enable-the-windows-subsystem-for-linux) to do that, **open PowerShell as administrator** and run:
```
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```

Then, you need to **enable Virtual Machine feature** [(Step 3)](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-3---enable-virtual-machine-feature), run:
```
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
```

**Restart your machine** to complete the WSL install and update to WSL 2.

**Download** the [WSL2 Linux kernel update package for x64 machines](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi). **Run it as administrator** [(Step 4)](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package)[^wsl-update-error].

To **set WSL 2 as your default version** [(Step 5)](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-5---set-wsl-2-as-your-default-version), run the following command:
```
wsl --set-default-version 2
```

## Install a Linux distribution

WSL is ready to run Linux on your machine, now you can install your favorite distribution [(Step 6)](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-6---install-your-linux-distribution-of-choice)

Open the **Microsoft Store**, then search and **install your desired Linux distribution**.

When the installation[^console-does-not-return] ends[^error-0xc03a001a], you will be prompted to **create your user** and **set your password**.  
Now you should be connected to your distribution with the user previously set[^connected-as-root].

You can see the installed distributions and their name with:
```
wsl -l -v
```

The default distribution is marked with a star, you can set a distribution as default with:
```
wsl --set-default <distro>
```

To launch the default distro you can execute the `wsl` command.

To launch a specific distro:
```
wsl -d <distro>
```

If you have a previously installed distribution using WSL 1 (VERSION is 1), you can upgrade it with:
```
wsl --set-version <distro> 2
```

This operation may take a long time.

## Install Docker Desktop

Following [Docker documentation](https://docs.docker.com/docker-for-windows/wsl), download and install [Docker Desktop](https://download.docker.com/win/stable/Docker%20Desktop%20Installer.exe)

You need to **activate Docker Desktop to your Linux distribution**, to do that, **open Docker Desktop dashboard** from the Windows task bar hidden icons.

Go to `Settings` > `Resources` > `WSL integration`, **activate WSL integration** for your distribution, then click on `Apply & Restart`.

## Install Windows Terminal

You may need a **better terminal** in order to have the full comfort of your Linux distribution, [Windows terminal](https://docs.microsoft.com/en-us/windows/terminal) fits our requirements. You can **Install the app** from the [Microsoft Store](https://www.microsoft.com/en-us/p/windows-terminal/9n0dx20hk701?activetab=pivot:overviewtab).

Once installed you can **customize the settings**, use this [JSON schema](https://aka.ms/terminal-profiles-schema) to see all the available options. To open the setting file, click the downside arrow in the top bar then click on `Settings` *(Ctrl,+)*.

To **change the default shell profile**, set the `guid` value of the profile you want as default in `defaultProfile`. Profiles guids can be found in the `profiles` section.

`"defaultProfile": "{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxx}",`

To **set your distribution home directory** as the starting path instead of the Windows mount location, add `~` to the `commandline` entry on your distribution profile.

```jsonc
"profiles": [
     #...
    "list": [
        #...
        {
            #...
            "name": "<distribution-name>",
            "source": "Windows.Terminal.Wsl",
            "commandline": "wsl.exe ~ -d <distribution-name>",
            #...
        }
        #...
    ]
    #...
]
```

### Terminal settings and shell override.

:warning: Windows terminal is a medium to interact with a shell. Some of the settings defined here might be overridden by the shell configuration.

### Configuration samples

#### Color scheme

Override the default color scheme and set a name.
```jsonc
"schemes": [
    #...
    {
        "name": "Gerbier",
        "background": "#111111",
        "foreground": "#C8C8C8",
        "black": "#C8C8C8",
        "blue": "#44637A",
        "brightBlack": "#7A7A7A",
        "brightBlue": "#6FA0C6",
        "brightCyan": "#76A394",
        "brightGreen": "#7CA661",
        "brightPurple": "#9090C0",
        "brightRed": "#B04646",
        "brightWhite": "#505050",
        "brightYellow": "#E8C273",
        "cyan": "#32464A",
        "green": "#425934",
        "purple": "#555573",
        "red": "#8A3737",
        "white": "#3C3C3C",
        "yellow": "#9C824D"
    }
    #...    
],
```
Reference your color scheme by associating the name to the colorScheme property.   
```jsonc
"profiles": [
     #...
    "list": [
        #...
        {
            #...
            "colorScheme": "Gerbier",
            #...
        }
        #...
    ]
    #...
]
```

#### Custom keybindings example
```jsonc
 "actions":
    [
        // Application-level Keys
        { "command": "closeWindow", "keys": "alt+f4" },
        { "command": "toggleFullscreen", "keys": "alt+enter" },
        { "command": "toggleFullscreen", "keys": "f11" },
        { "command": "toggleFocusMode" },
        { "command": "toggleAlwaysOnTop" },
        { "command": "openNewTabDropdown", "keys": "ctrl+shift+space" },
        { "command": "openSettings", "keys": "ctrl+," },
        { "command": { "action": "openSettings", "target": "defaultsFile" }, "keys": "ctrl+alt+," },
        { "command": "find", "keys": "ctrl+f" },
        { "command": "toggleRetroEffect" },
        { "command": "openTabColorPicker" },
        { "command": "commandPalette", "keys":"ctrl+shift+p" },

        // Tab Management
        // "command": "closeTab" is unbound by default.
        //   The closeTab command closes a tab without confirmation, even if it has multiple panes.
        { "command": "closeOtherTabs" },
        { "command": "closeTabsAfter" },
        { "command": "newTab", "keys": "ctrl+t" },
        { "command": "duplicateTab", "keys": "ctrl+d" },
        { "command": "nextTab", "keys": "ctrl+tab" },
        { "command": "prevTab", "keys": "ctrl+shift+tab" },

        // Pane Management
        { "command": "closePane", "keys": "ctrl+w" },
        { "command": { "action": "splitPane", "split": "horizontal" }, "keys": "alt+shift+-" },
        { "command": { "action": "splitPane", "split": "vertical" }, "keys": "alt+shift+plus" },
        { "command": { "action": "resizePane", "direction": "down" }, "keys": "alt+shift+down" },
        { "command": { "action": "resizePane", "direction": "left" }, "keys": "alt+shift+left" },
        { "command": { "action": "resizePane", "direction": "right" }, "keys": "alt+shift+right" },
        { "command": { "action": "resizePane", "direction": "up" }, "keys": "alt+shift+up" },
        { "command": { "action": "moveFocus", "direction": "down" }, "keys": "alt+down" },
        { "command": { "action": "moveFocus", "direction": "left" }, "keys": "alt+left" },
        { "command": { "action": "moveFocus", "direction": "right" }, "keys": "alt+right" },
        { "command": { "action": "moveFocus", "direction": "up" }, "keys": "alt+up" },

        // Clipboard Integration
        { "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+c" },
        { "command": { "action": "copy", "singleLine": false }, "keys": "ctrl+insert" },
        { "command": "paste", "keys": "ctrl+v" },
        { "command": "paste", "keys": "shift+insert" },

        // Scrollback
        { "command": "scrollDown", "keys": "ctrl+down" },
        { "command": "scrollDownPage", "keys": "ctrl+pgdn" },
        { "command": "scrollUp", "keys": "ctrl+up" },
        { "command": "scrollUpPage", "keys": "ctrl+pgup" },

        // Visual Adjustments
        { "command": { "action": "adjustFontSize", "delta": 1 }, "keys": "ctrl+=" },
        { "command": { "action": "adjustFontSize", "delta": -1 }, "keys": "ctrl+-" },
        { "command": "resetFontSize", "keys": "ctrl+0" },

        // Other commands
        {
            // Select color scheme...
            "name": { "key": "SetColorSchemeParentCommandName" },
            "commands": [
                {
                    "iterateOn": "schemes",
                    "name": "${scheme.name}",
                    "command": { "action": "setColorScheme", "colorScheme": "${scheme.name}" }
                }
            ]
        },
        {
            // New tab...
            "name": { "key": "NewTabParentCommandName" },
            "commands": [
                {
                    "iterateOn": "profiles",
                    "icon": "${profile.icon}",
                    "name": "${profile.name}",
                    "command": { "action": "newTab", "profile": "${profile.name}" }
                }
            ]
        },
        {
            // Split pane...
            "name": { "key": "SplitPaneParentCommandName" },
            "commands": [
                {
                    "iterateOn": "profiles",
                    "icon": "${profile.icon}",
                    "name": "${profile.name}...",
                    "commands": [
                        {
                            "command": { "action": "splitPane", "profile": "${profile.name}", "split": "auto" }
                        },
                        {
                            "command": { "action": "splitPane", "profile": "${profile.name}", "split": "vertical" }
                        },
                        {
                            "command": { "action": "splitPane", "profile": "${profile.name}", "split": "horizontal" }
                        }
                    ]
                }
            ]
        }
    ]
```

## Next article

In the next article [A better shell with oh-my-zsh](https://dev.to/codingones/a-better-shell-with-oh-my-zsh-1m0h) we will focus on customizing the shell.

## Contributors
[Romain Cambonie](https://www.linkedin.com/in/romain-cambonie/)
[Marc Gavanier](https://www.linkedin.com/in/marc-gavanier/)

## References used

- [WSL Documentation](https://docs.microsoft.com/nl-nl/windows/wsl/)
- [Docker Desktop for windows](https://docs.docker.com/docker-for-windows/wsl/)
- [Windows Terminal](https://docs.microsoft.com/nl-nl/windows/terminal/)
- [Windows Terminal JSON Schema](https://aka.ms/terminal-profiles-schema)
- [Linux kernel WSL 2 update](https://docs.microsoft.com/nl-nl/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package)
- [Troubleshooting: error 0xc03a001a - 1](https://utf9k.net/blog/wsl2-vhd-issue/)
- [Troubleshooting: error 0xc03a001a - 2](https://github.com/microsoft/WSL/issues/4103)

[^check-for-updates]: To see the Windows version 2004 update you may have to click on `Check online for updates from Microsoft Updates`, just under the button `Check for updates`

[^already-have-docker-desktop]: If you already have docker desktop installed on your machine, you will be prompted with a message that invites you to use WSL 2 instead of HyperV. This will be addressed later in this tutorial.

[^wsl-update-error]: If you cannot run `wsl_update_x64.msi` as administrator, the installation may end with the following error:
    `This update only applies to machines with the Windows Subsystem for Linux`
    To get around this problem, open PowerShell as administrator and run the installation via CLI.

[^console-does-not-return]: You may need to press enter if you feel that the installation takes too long. Installs should typically take under a minute.

[^error-0xc03a001a]: You may encounter the following error:
    `Error: 0xc03a001a The requested operation could not be completed due to a virtual disk system limitation.  Virtual hard disk files must be decompressed and unencrypted and must not be sparse.`  

    To fix this error, go to `$USER\AppData\Local\Packages`, and find the package of the distribution (eg: CanonicalGroupLimited.Ubuntu20.04... ), open the folder properties `General > Advanced`, then uncheck `Compress and Encrypt attributes`.


[^connected-as-root]: If you are connected as 'root' on your distribution, the installation failed somewhere, the easier option is to uninstall and reinstall. Run `wsl --unregister <distro>` Launch your distribution again from the Windows Store to restart the installation.