Webdev on Windows with WSL and VS Code

The 2018 Edition of my step-by-step guide of setting up Linux, Git, Ruby, Rails, Python, Node, and Visual Studio Code on Windows 10

April 25, 2018

This month I recently had the unfortunate pleasure of re-installing Windows on all my computers due to some botched Windows Insider updates. Yeah… ouch.

But I got good at replicating my dev environment! So I thought it’d be a good chance write an update on setting up a modern web development environment on Windows 10 using the Windows Subsystem for Linux (WSL) and Visual Studio Code.

Install Linux on Windows

Linux distributions inside Window Store

The first step is to install an operating system on your operating system. Let’s follow the steps from https://aka.ms/wslinstall. First, open Powershell by searching for it in Cortana and right-clicking for a context menu and clicking “Run as Administrator”. Enter the following command:

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

Next step, go to the Windows Store and choose your flavor of Linux. I like Ubuntu because it’s a pretty common development environment and most readme docs and tutorials are written for it.

Launch Ubuntu.exe from the Start Menu. You’ll be asked to enter a username and password (for sudo stuff). Congrats! You’ve installed Linux. In fact, that’s probably the easiest way ever to install Linux. It’s very vanilla though. We’ll need to install all the Web Development goodies, but first let’s install Visual Studio Code.

Install Visual Studio Code for Windows

First, Download Visual Studio Code for Windows from the website. Juggling two operating systems is a little confusing, you just installed Linux but we want the Windows-version of Visual Studio Code that we can launch from the Taskbar and Start Menu. We’ll edit all our project files in the Windows realm.

When you open Visual Studio Code for the first time you’ll get an error:

⚠ Git not found. Install it or configure it using the 'git.path' setting.

This is telling us we don’t have git yet installed. Git in needed to power the Source Control panel in the VS Code workspace. Again this is a bit confusing because we’ll probably need to install git on both Windows and Linux. Let’s unblock the Windows side of things…

Install Git for Windows

Download Git for Windows from the git-scm website. Follow the Install Wizard.

For the curious, here are some options I modified...
  • Unchecked the "Windows Explorer integration" and checked the "Check daily for Git for Windows updates" options.
  • Checked "Don't create a Start Menu folder"
  • Selected "Use VisualStudioCode as Git's default editor"
  • Selected "Use Git from the Windows Command Prompt" (said "no" to the optional Unix tools in my Windows Command Prompt)
  • Selected "Use the OpenSSL library"
  • Selected "Checkout as-is, commit Unix-style line endings" - Your mileage may vary, but Code seems to handle LF endings fairly well. And any CRLF endings you create Windows be converted back to LF when committing. This is a magic sauce for Win-to-Unix compatibility.
  • Selected "Use Windows' default console window"

Now Code should be using Git for Windows. Opening Code we get a new fatal: Not a git repository error, this is because we haven’t opened a project with a git repository yet.

Configure VS Code to use Bash

One more thing you’ll want to do before you start downloading projects is set Bash to be the default terminal for VS Code. This is my primary way to interact with the Linux. To do this, open settings and add this rule to your User Settings:

"terminal.integrated.shell.windows": "C:\\WINDOWS\\sysnative\\bash.exe"

Restart VS Code and use CTRL + ` to open the Integrated Terminal (or search “Integrated Terminal” in the Command Palette). You should now be all setup and ready to web develop.

👉 One thing I want to call out here is the path in your Bash prompt, it should look something like…

<bashusername>@<computername>:/mnt/c/Users/<winusername>

This is key in understanding where Windows expects your project files to live. Which leads me to my most Frequently Asked Question…

FAQ: Where do my project files live?

This is where the WSL and a normal Linux workflow get a little different. When working with projects in WSL you want to save your project files in your Windows User Home directory. This lets any Windows App access or manipulate files your project files. Image exporting and compression is a pretty common task, but it could be as basic as right-click “Open with VS Code” in File Explorer. In Windowslandia, that’s:

C:\Users\<winusername>\

In WSL, this maps to:

/mnt/c/Users/<winusername>$

The /mnt/c/ shortcut maps to your “mounted” C:\ drive. So if I keep my files in C:\Users\Dave\Documents\Github I get there by typing:

cd /mnt/c/Users/Dave/Documents/Github

From this directory, I create/clone projects. Then using Bash, I cd into those directories and npm install / bundle install whatever I need. When you npm install files here from the command line, you’ll see your node_modules fill up in File Explorer, but all binaries and executables like libsass are compiled for Linux (I don’t know how, but it works).

My common workflows work like this: Start tasks (webpack, build processes, webservers) in Bash on WSL, then edit your project files using Windows apps.

If you come from a Unix background this gets confusing. Opening a Bash shell and typing cd ~ && pwd in WSL gets you the following…

/home/<bashusername>

This is not the same as your Windows User Home directory. This home folder actually maps to a hidden folder that Linux uses deep inside your User AppData directory…

C:\Users\<winusername>\AppData\Local\Packages\<distroname>\LocalState\rootfs\home\<bashusername>

Don’t open these files with Windows. Just ignore the files here. Editing these files with a Windows app can explode your Linux distro.

What do you use ~ for then? Good question! I use my $HOME directory to install nvm and rbenv or any other command-line utilities. I also edit my Dotfiles (like .bash_profile) that live in this directory with vim or nano (remember don’t edit these files with Windows apps or else it might explode).

Install Git, Python, Node, and Ruby on WSL

Now that we have our editor and shell setup, let’s install what we need to make websites inside the VS Code Integrated Shell.

Installing Git on WSL

We already installed Git for Windows, but let’s install Git on your Linux distro so we can use Git from inside Bash.

sudo apt install git
git config --global user.email "you@example.com"
git config --global user.name "Your Name"
git config --global core.autocrlf input

The core.autocrlf=input setting is pretty crucial. It can break things you install over git (like rbenv). If you have 2FA enabled on Github (you should), you’ll also need to follow the Add SSH Key to Github and be sure you’re using the Linux instructions.

Installing Python

Python is probably the easiest to install.

sudo apt install python3
echo "alias python='python3'" >> ~/.bashrc
source ~/.bashrc

Aliasing python3 to python can be dicey if you install something that expects python to be Python 2.

Installing Node

Node is almost as easy to install, let’s use nvm for that inevitable day where we have to support mutliple versions of Node.

curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.9/install.sh | bash
source ~/.bashrc
nvm install --lts

You should now have node and npm installed.

Installing Ruby and Rails

Ruby has a few more dependencies. Thankfully WSL has improved so that we can follow any generic “How to Install Ruby on Rails” tutorial, I like this one from Digital Ocean.

sudo apt install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
git clone https://github.com/rbenv/rbenv.git ~/.rbenv
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(rbenv init -)"' >> ~/.bashrc
source ~/.bashrc
git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.5.1 --verbose
rbenv global 2.5.1
echo "gem: --no-document" > ~/.gemrc
gem install bundler
gem install rails

You don’t technically need --verbose for installing Ruby via rbenv, but having some progress indicator helps with your sense of time.

It keeps getting better

Hopefully now you have a workable developer environment! WSL has brought me a lot of joy and productivity over the last couple years. Forced re-installs aside, it’s never been easier to do webdev on Windows (except maybe in circa 2000 when Frontpage was super popular).

One major difference this time around is I didn’t install Hyper and its Node for Windows dependency on my Windows system. I still love Hyper, but I can suffer through the default Ubuntu.exe app when out-of-editor. The Windows Console team now have a commandline tool to change colors, copy/paste and a tabbed console in Insiders builds. Not perfect yet but gets the job done.

One thing I didn’t cover completely is databases. The Rails install includes SQLite, but I’ll update this guide as I go through the process of installing other databases (MySQL, Postgresql, Mongo, etc). I also didn’t cover languages like Go or Rust which I hope to get into this year. I’ll try to get on this.

I’m on the 2017 Fall Creator’s Update and a few things don’t work: the new Jekyll Livereload feature, ngrok, and some background tasks. But all these are fixed in the Insider builds and should land in the 2018 Spring Windows Update that drops soon.

Like I said, it keeps getting better and the problems keep becoming fewer as time goes on.