WSL and Ubuntu Web Development Setup
I have been using Windows + WSL2 (Ubuntu) for my web development environment for many years now.
Over time I gathered some helpful resources for setting up such development environment, so I decided
to write this post to have a reference for myself and you, dear reader!
It shows how to set up
- WSL and Ubuntu itself
- git-related tooling
- prerequisites to be able to install, build, etc. codebases using the Node.js ecosystem
- pnpm
- Docker
- VS Code
- and, optionally, additional things
Basic setup for WSL #
-
Open PowerShell as administrator and run:
wsl --install
-
Restart your machine.
-
Run "Ubuntu" from the start menu to start an Ubuntu terminal.
-
It will ask for a username and password - choose some.
-
I like to not having to enter the password when running things in the WSL distribution, do the following to remove it:
-
Run:
sudo visudo
-
At the bottom of the file, add the following line (replace
<username>
with your chosen username):<username> ALL=(ALL) NOPASSWD: ALL
-
Press
CTRL+X
to exit nano and it will prompt you to save. -
Close the terminal and start a new one (by running "Ubuntu" from the start menu).
-
-
Update and upgrade all packages:
sudo apt update && sudo apt upgrade
Ensure reliable network connection for WSL #
Sometimes after I have set up WSL it had strange network issues for outbound connections.
I found some GitHub issues regarding that and one of them mentioned a misconfigured network interface.
That's why nowadays I always do the following one time after setting up WSL (based on ):
-
Start PowerShell as administrator.
-
List the network interfaces of Windows:
netsh interface ipv4 show subinterfaces
-
There should be an interface called
"vEthernet (WSL)"
. Also you must have some WiFi interface, in my case it is called"WiFi"
. Both interfaces should have the same "MTU" value.
If not, run this:netsh interface ipv4 set subinterface "vEthernet (WSL)" mtu=<MTU-value-of-wifi-interface> store=persistent wsl --shutdown
Git and GitHub SSH #
-
Update git to the latest version and add support for git LFS:
sudo apt-get install git sudo apt-get install git-lfs git lfs install
-
Configure git:
git config --global user.name "Your Name" git config --global user.email "your_email@example.com"
-
Create a SSH keypair and add the private key to ssh-agent in Ubuntu (based on ):
# Generate a SSH keypair # When asked for a passphrase, I typically omit that. ssh-keygen -t ed25519 -C "your_email@example.com" -f "~/.ssh/id_rsa_github" # Start the ssh-agent in the background eval "$(ssh-agent -s)" # Add your SSH private key to the ssh-agent ssh-add "~/.ssh/id_rsa_github" # Configure the key for github.com in the SSH config file printf "Host github.com\n IdentityFile ~/.ssh/id_rsa_github" >> ~/.ssh/config # copy the public key into Windows clipboard cat "~/.ssh/id_rsa_github.pub" | clip.exe
-
Add the public key of your new SSH keypair to your GitHub account (note: you must check out the GitHub repositories via SSH then, not via HTTPS):
- Open new SSH key of your GitHub settings
- Title: I recommend to combine the name of your PC with "WSL", like
ZEPHYRUS-M16 WSL
. - Key type: Keep
Authentication Key
- Key: Use the content of the clipboard (= the public key).
Node.js and C/C++ compiler tool chain #
-
Instead of installing Node.js directly I like to use
nvm
to be able to have multiple versions of Node.js installed at the same time (you can read more here: ).
Run this to installnvm
:# replace v0.39.3 by the newest version # you can look it up here: https://github.com/nvm-sh/nvm/releases curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
-
To be able to compile npm packages which include native C++ addons, via
node-gyp
, we need to install a few things:sudo apt-get install build-essential g++ libx11-dev libxkbfile-dev libsecret-1-dev python-is-python3
-
npm has a feature to complete commands via the tab key, so let's enable that:
npm completion >> ~/.bashrc
-
If you want to automatically switch the Node.js version when you enter a directory with a
.nvmrc
file, you can run the code below in bash to add a hook to your.bashrc
:cat >> ~/.bashrc <<- EOM # start: run-nvm-use-if-cwd-has-nvmrc-file # run "nvm use" automatically on directory change if a file ".nvmrc" is present in the new directory (https://stackoverflow.com/a/48322289/1700319) _nvmrc_hook() { if [[ $PWD == $PREV_PWD ]]; then return fi PREV_PWD=$PWD [[ -f ".nvmrc" ]] && nvm use } if ! [[ "${PROMPT_COMMAND:-}" =~ _nvmrc_hook ]]; then PROMPT_COMMAND="_nvmrc_hook${PROMPT_COMMAND:+;$PROMPT_COMMAND}" fi # end: run-nvm-use-if-cwd-has-nvmrc-file EOM
pnpm #
-
To just use
p
to runpnpm
, add the following to your.bashrc
:cat >> ~/.bashrc <<- EOM # start: pnpm-alias alias p='pnpm' # end: pnpm-alias EOM
Docker #
Choose one of the following:
- Docker Desktop: This is the recommended option because everything just works.
- Install Docker directly in WSL Ubuntu: Drawbacks are that there is no support for starting containers from Windows directly and multi-platform builds are not possible with this option.
Dockerfile linting via hadolint #
-
# replace v2.10.0 by the newest version # you can look it up here: https://github.com/hadolint/hadolint/releases wget -O /bin/hadolint https://github.com/hadolint/hadolint/releases/download/v2.10.0/hadolint-Linux-x86_64 sudo chmod 777 /usr/bin/hadolint
Docker multi-architecture builds #
Set up a multi-architecture Docker builder for cross-platform builds:
# from https://unix.stackexchange.com/a/748634
docker buildx create --use --platform=linux/arm64,linux/amd64 --name multi-platform-builder
docker buildx inspect --bootstrap
VS Code #
-
Install the extension, then you can run in an Ubuntu terminal
code .
to start VS Code in that folder.VS Code will inherit all environment variables from the WSL terminal, and
nvm
uses environment variables to switch Node.js versions.
As a consequence, VS Code started this way will under-the-hood use the exact version of Node.js you want to use for the project, allowing e.g. git hooks invoked by VS Code to work correctly.I use scripts like below to quickly start development:
alias pkerschbaum_dev='cd ~/workspace/pkerschbaum-homepage && nvm use && code .'
Additional things #
-
ngrok
is a great tool to expose a local server to the internet (e.g. to open the web application you work on on your mobile phone). -
To sync the bash history between terminals, run the following in the Ubuntu terminal to add it to your
.bashrc
:cat >> ~/.bashrc <<- EOM # start: sync-bash-history # sync history between terminals, https://subbass.blogspot.com/2009/10/howto-sync-bash-history-between.html shopt -s histappend PROMPT_COMMAND="history -n; history -a" unset HISTFILESIZE HISTSIZE=2000 # end: sync-bash-history EOM
-
Certain Node.js and Ubuntu combinations can lead to errors when Node.js
crypto
APIs are used. In case you get an error along the lineserror:25066067:DSO support routines:dlfcn_load:could not load the shared library
when running Node.js code you can do this: . -
If there are connection issues (even after fixing the MTU value of the WSL network interface, what we did above) you might need to change the DNS server: .
-
Some WSL tips:
- Run
explorer.exe .
in an Ubuntu terminal to open the Windows Explorer at that directory path. - Run
echo "hello world" | clip.exe
to copy "hello world" to the Windows clipboard. - Run
wsl --shutdown
in Windows CMD or PowerShell to shutdown the WSL instance.
- Run