Setting up WSL 2 for Web Development
Recently, WSL 2 landed on the slow ring of Windows Preview. As a fan of WSL myself, I am eager to try it out and enjoy the improved I/O performance it brings to the table. So without further delay, I opted in and upgraded Win10 2004 and enabled WSL 2. HOWEVER (there is always a “however”), not all things are smoothed out yet at the time of writing. In this post, I am going to write about my experience of setting up WSL 2 for a Django web development workflow.
A few things to pay attention to here:
WSL 2 I/O Performance Catch
WSL 2 has a much improved I/O performance, but only on the Linux partition. As described in this documentation WSL 2 has a much slower performance when performing cross OS I/O tasks. Outcome include:
- Unacceptable slow performance with zsh shell prompt/plugins, like oh-my-zsh or starship. I don’t know how the internal implementation of these projects to identify the direct reason, but the outcome is printing a new line takes over 30s 🙃:
- Slow start up performance. Sometimes the WSL prompt can take over 15s to start. One way to mitigate this is to exclude the inclusion of Windows PATH, with which I can reduce the start up time down to 1s. This will be elaborated in the next point.
If you are interested you can follow up the progress at this Github issue. Note that the problem is clearly known and actively working on so hold yourself from spam the thread with +1 comments.
Exclude Windows PATH
As mentioned, excluding Windows PATH can bring some nice performance boost. If you are not relying Windows programs anyways, you can safely exclude it by adding this to
“But what about VS Code?! 😱” Don’t worry my friend. I have you covered. Notice that we have a special alias on line 22 of the
With this alias we can now use the
code command inside WSL 2 as we would in any local shell terminal.
Zsh History Search & Starship
With a ton of experiments, some of which can be seen in this GitHub issue, my zsh with oh-my-zsh was proven to be slow in WSL 2. Slower than I would like, at least. I used to be a big fan as it really helps configure a nice and usable zsh out of the box. However, it includes too many things under the hood which I don’t really need. Some of the features I would really like to keep are:
- Menu-like options when hitting Tab, which is built-in and can be enabled like shown at the beginning of my
- A nice-looking theme. I really like the spaceship theme
- History search with up arrow key
After searching for a while, I landed on starship, a Rust-powered and spaceship-inspired cross-shell prompt which also works with Powershell (Yay!! 🤗), and this nice zsh-history-substring-search plugin. I installed the latter via homebrew. You can configure them just like I did at the end of the
Typeface & Nerd Font
As you would expect from a spaceship theme user, I like icons and emojis. However, not all emojis look nice in every terminal on every OS. On the other hand, nerd font icons are much are consistent and renders nicer in VS Code’s built-in terminal. You can find a preset config from starship.
A nice typeface is also critical to a nice CLI experience. As a diehard Consolas fan, I’ve always been looking around for an open-source alternative that I can use across all systems. Luckily, that mission was recently accomplished: Code New Roman and its nerd font version CodeNewRoman Nerd Font. Give them a try if you share the love for Consolas!
Python & Node
As you might have noticed, I use miniconda and nvm for managing Python and node/npm versions. You can install them simply by running:
If you know Anaconda, miniconda is just a stripped-down version of it. I like using it because of its separation from the system Python: I don’t need to worry about breaking some system packages when I upgrade my Python installation. Conda, the dependency manager miniconda uses, can also identify packages that need upgrade and resolve conflicts when you bump up the Python version. At the time of writing, miniconda only comes with Python 3.7. However, you can easily upgrade to Python 3.8 by:
If you want to upgrade, please do this right after installing miniconda as I’ve experienced some failures with a dozen packages already installed. For my purpose, Django already support Python 3.8 since 2.2.8 so it’s safe to make the upgrade.
Web & Database
Here comes the (a bit) more tricky part. IIRC, previously in WSL 1, you can access the host (Windows) database from inside WSL. Due to the architecture change in WSL 2, you are not able to do that out of the box. Here in this section it says:
To access a Windows network application you’ll need to use the IP address of your host machine.
You can do so by
cat /etc/resolv.conf inside WSL, copy the IP address following “nameserver” and use it in your CLI:
Easy enough for web services. But what about database? Well, here you have two options.
Install Database in WSL
One of the more straightforward option is to install your database server inside your WSL 2. It is just the same as installing your database on any Ubuntu-based distro. As for my project, I use MariaDB and you can find the official instructions here. You will be able to start the database server with
sudo service mysql start. The problem comes after the installation: How do I inspect the database with my favorite GUI tools like DataGrip/DBeaver/Sequel Pro from Windows?
First, if you have a database server running on you Windows host, make sure to change either one of the ports your database is running on. Then, bind your WSL 2 database to the address
0.0.0.0. These settings can be applied by adding the following lines to your
After editing, make sure to restart the database server by
sudo service mysql restart. Now you should be able to access your WSL database via
Accessing Database Running on Windows from WSL
TL;DR I personally don’t recommend this approach because it requires much more workaround.
Warning: This approach relies on the IP addresses on both the host and guest machine pointing to each other. As Uzume stated here, WSL 2 acts more like a virtual machine compared to WSL 1. HOWEVER, these IP addresses are NOT fixed! They change on every reboot so you have to reconfigure something every time.
As shown in the graph above, in the current setting, WSL 2 can access Windows application via
172.21.64.1, which is the IP address in
/etc/resolv.conf. By default, Windows share the
127.0.0.1 with WSL 2 and can access network applications running in WSL 2 via
127.0.0.1:<port> as shown above. You may wonder, “Well, what’s the use of that
172.17.131.186 in this case and where does it come from?” 🤔
That’s a great question. Databases, out of security consideration, do not allow remote access by default. You have to manually grant remote access to specified IP addresses if you want to do so. Let’s first try to connect to the MariaDB running on Windows from WSL 2 first and see what will happen:
At this point, you will likely encounter some error message like this:
Here we get
172.17.131.186, the IP address of our WSL 2 virtual machine on Windows. Seeing this error message is actually a good sign as it indicates you can hit the database but just don’t have the access right. What you need to do now is to configure your database server for remote access and grant access to your WSL 2’s IP address
172.17.131.186. For MariaDB, the instructions can be found here. Following the instructions, we start the MySQL client command prompt, log in and type:
You might need to restart the MariaDB server for it to take effect. If all goes well, you can now access the Windows MariaDB from WSL 2:
Now you can put the database host info in your web app’s settings. For example, in Django’s setting file:
Microsoft really provides great tooling for your development workflow on WSL. No surprise, my editor of choice is VS Code. For remote development using WSL, check out this guide if you haven’t. Not everything applies to WSL 2 just yet but it’s still a nice guide. What we need most is the Remote - WSL extension. With it installed, we can now go to any working directory, type
code ., open up VS Code and start working. Install the extensions you need and enjoy the Linux dev workflow on Windows!
In this post, I discussed how to set up WSL 2 for web development (Django and Vue in my case). Aspects covered include setting up zsh without the dependency on oh-my-zsh, installing Python and Node, and setting up the database for web development.
Finally, a big THANK YOU to the awesome folks behind the WSL project! 💖 Thanks for making this possible and I really look forward to the first official release!
I hope you find this post helpful. Thanks for stopping by!