Setting up a node.js development environment in WSL 2

noejon profile image Jonathan Noé ・9 min read

G'day Internet,

Here we are with the first article I am releasing on the web. And today we will talk about Windows Subsystem for Linux, a feature released as part of the insider build 18917. We will attempt to install WSL2 and setup a node.js development environment.

Windows has a Subsystem for Linux since 2016. It enabled us to use Linux distributions on our Windows 10 systems. It now comes with Windows Subsystem for Linux 2, with a shift in their architecture, improving both the performance and the compatibility between windows and the subsystem. Further information can be found in Microsoft's developer blog

Node.js development environment

The development environment we will set up is composed of:

  • git as our version control system.
  • zsh and oh-my-zsh to replace bash (optional).
  • visual studio code as our text editor.
  • node.js and npm.
  • docker and docker-compose to containerise our projects .

But first we need to install WSL2.

Installing WSL2

Windows insider

The first thing we are going to do is enable the Windows Insider Program

It can be enabled in the Settings > Update and Security > Windows Insider Program. Here are the steps

  • Logging in to Windows Insider account or create one.
  • At the time of writing, WSL2 is in the Fast builds, so the insider settings should be set to Fast.
  • Then we head to settings > Update and Security > Windows Update and check for updates. We then install the latest build, then restart our machine.
  • We should now have the latest updates, and with that comes WSL2. Next we will see how we can activate WSL2.


In order to install WSL2, WSL the first needs to be installed. Open a Powershell (as an Administrator) and type:

Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

When prompted to restart our machine, we just answer with [Y]es.

After the computer restarted, we head to the Microsoft Store and search the term linux.

After clicking on Run Linux on Windows we choose to get ubuntu as our linux distribution. Once ubuntu is installed, we launch it. After a first initialization we are prompted for the Unix username and the Unix password. We then update ubuntu's package manager (this might take some time and you will be prompted for information twice, normally).

sudo apt update && sudo apt upgrade

We are now one step away from enabling WSL2.


Let's open a powershell again, and enable another optional feature

Enable-WindowsOptionalFeature -Online -FeatureName VirtualMachinePlatform

Again, we are prompted to restart the system. [Y]es again.

After the machine rebooted, we open a powershell as Administrator for the last time, to make sure that we make use of WSL2!

wsl --set-version ubuntu 2

This process might take a few minutes, says Powershell.

Note: I have ran this installation on two different machines during the same week, and once I had to type ubuntu and the other one ubuntu-18.04. There are several ubuntus in the store, I might have picked different ones.

Next we set WSL2 as our default choice for WSL

wsl --set-default-version 2

And this is it, we have now successfully installed WSL2. Time to set up our development environment.

Linux files

The release announcement blogpost asks us "To make sure to put the files that we will be accessing frequently inside of our Linux root file system to enjoy the file performances benefits".

We can now access files from the windows explorer. It is as easy as typing \\wsl$\Ubuntu\home in the explorer navigation bar. We are now in our home folder.
The home folder can be pinned to Quick access

Most of the installation will happen in the ubuntu console. As good practice, before installing anything on linux run

sudo apt update && sudo apt upgrade

We can now start setting up our development environment.

Changing bash to zsh

In this section we are replacing the default bash terminal with zsh and oh-my-zsh. You can skip to the development tools section if you plan to keep use bash

To install zsh we open a terminal (the ubuntu app) and run

sudo apt install zsh

zsh can now be launched just by typing zsh in the terminal. A .zshrc file needs to be created, and we are prompted for a choice. He we pick (0) as the .zshrc file will be replaced when we install oh-my-zsh.
We don't want to type zsh each and everu time we start the ubuntu app, so the next thing we want to is change the default shell to use zsh. To do so, we'll use the chsh command as per this example. Simply run

chsh -s $(which zsh)

After this is done, we will change the theme of our zsh and to do so, we will leverage the power of oh-my-zsh. A simple command will install it:

sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)"

I changed my theme to the lambda theme but feel free to choose amongst all other existing themes and follow the instructions there to change.

zsh also comes with a set of plugins that could be useful to increase your development speed. Completion plugins are also available for npm. Please refer to the plugin page to find anything that suits you. I enjoy working with the git plugin. Talking about git, it is the next tool we are going to install.

Note: When running sudo apt upgrade or sudo apt-get update, the following error code could be encountered:

E: Release file for https://download.docker.com/linux/ubuntu/dists/bionic/InRelease is not valid yet (invalid for another 15h 3min 13s). Updates for this repository will not be applied.

This is dues to a known issue in WSL. A temporary fix is to call

sudo hwclock -s

Development tools



To install git, in a wsl terminal, we run

sudo apt update && sudo apt upgrade
sudo apt install git

End of line

The next step is to deal with cross plateform problems, where sometimes git recognise changes in files, when there are none. This is due to windows using CRLF and linux LF to signify an end of line. To fix that, the following line can be run:

git config --global core.autocrlf input

Configuring SSH

First we create a SSH key on your new linux subsystem. Instructions can be found (here)[https://help.github.com/en/enterprise/2.15/user/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent]

To generate a private and a public key for git, we run:

ssh-keygen -t rsa -b 4096 -C "email@email.com" #replace with your email

This will generate a new ssh key. When prompted to choose a file where the key will be saved, we can use either the default location or input your preferred location for the file. For this example we will consider that we used the default location ~/.ssh/id_rsa

Start the ssh-agent:

eval "$(ssh-agent -s)"

We then add the ssh private key to the ssh-agent

ssh-add ~/.ssh/id_rsa

After that we can add the key to a github or a (gitlab)[https://docs.gitlab.com/ee/ssh/#adding-an-ssh-key-to-your-gitlab-account] account.

Note: I currently need to run eval "$(ssh-agent -s)" and ssh-add ~/.ssh/id_rsa every time I restart my laptop.

Now that we installed git, we are sure that the code we write does not get lost. Now to write our code, let's install Visual Studio Code.

Visual Studio Code

We browse (the Visual Studio Code website)[https://code.visualstudio.com/], download visual studio code for Windows, and install it.

During the installation process, we make sure to check the box to add Visual Studio Code to the PATH, it is recommended for an extension we'll install later.

Code comes with heaps of extensions, but the one we are interested in is VS Code Remote Development. It bundles a few extensions that are useful for remote development, including Remote - WSL which will do some magic for us.

In VS Code, in the extension tab we look for Remote Development and install it.

In a zsh terminal we browse to our home folder and create a dev folder:

cd ~ && mkdir dev && cd dev

Now we just start code from a ubuntu terminal

code .

It should open a new VS Code window, and install a VS Code server on our WSL. Once this is done, we can now create files in our editor and they will be created in the linux file system.
This article is written using exactly this setup \o/

This last part is for those among us who installed zsh. Once VS Code is connected to WSL, it is possible to modify the default shell to be zsh. This will take effect after relaunching the terminal.

Now that we have installed Visual Studio Code, let's install node.js


Node Version Manager (nvm)

To install node.js we will leverage nvm. The installation is once again quite straight forward. In a ubuntu terminal we run:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.34.0/install.sh | zsh

Note: If you did not install zsh, the previous command should be run with bash instead of zsh.

If the installation is successful the following command should return nvm. If it does not, a simple restart of the terminal should fix it.

command -v nvm

Installing node and npm

Let's have a look at the commands available in nvm

nvm --help

The command we are interested in in the nvm install command. Let's install node's latest LTS (Long-term support) version:

nvm install --lts

That's it, we installed node and npm. But let's check that I am not lying by checking the versions.

node --version && npm --version

Our journey to set up our development environment is almost complete. The last thing we need to do is to take one last (whale-)boat trip. Here comes Docker.


Docker CE

To install docker, we will follow the steps from the official documentation

First we need to update apt-get

sudo apt-get update

After what we install a few required dependencies

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \

We then need to add Docker's official GPG key

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

We need to make sure that we have the key with fingerprint 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88

sudo apt-key fingerprint 0EBFCD88

Docker needs to be added to the list of repositories

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \

Note: My processor is an amd64 process, if you have a different type of processor, replace [arch=amd64] accordingly (other possible values: armhf, arm64, ppc64e1 and 390x).

We are now ready to install (Docker Community Edition)[https://docs.docker.com/install/]

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

Now let's make sure that docker is installed.

sudo docker run hello-world

This should download a test image and run it in a container. If the docker service is not started, it needs a (manual kickstart)[https://docs.docker.com/config/daemon/systemd/] and in our case, with ubuntu we will use:

sudo service docker start
sudo docker run hello-world

Docker Compose

In this world full of microservices, a tool such as docker compose is a time saver. It allows us to run several application containers from one single command. The installation steps are as follows:

First download the stable release of Docker Compose (1.24.1 at time of writing)

sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Once the binary is downloaded, it needs to have execution permissions:

sudo chmod +x /usr/local/bin/docker-compose

Finally we check the installation by running

docker-compose --version

which should return a docker-compose version and a build id (docker-compose version 1.24.1, build xxxxxxxx at time of writing)

We have now installed the tools for us to start developing node apps. WSL2 is currently only in beta mode, so we will most likely encounter issues. Don't hesitate to report any issue encountered (double checking first if the issue has been encountered yet).

I hope that you enjoyed this article, the first one I ever wrote. Feel free to leave some feedback.

That's all folks!



Editor guide
miguemartelo31 profile image