Learn how to transform your Windows 10 machine into a Linux powerhouse.
Imagine for a moment that you're stranded on a desert island. You're a software developer and have been using Linux systems or an Apple Mac ever since you were old enough to type on a keyboard. Yet the only things that you were able to bring with you to your desert island was a Windows machine, and enough tea and biscuits to last a lifetime. Luckily the island already has an internet connection — what do you do?
Okay, you could just download Ubuntu and install it onto a Virtual Machine, but there is another way. Which as it happens, also involves installing Ubuntu...
I was in a very similar situation recently, although instead of being stranded on a desert island I was forced to leave my MacBook with the Apple Store while they fixed a weird issue with my touch bar.
I had to find a way to keep working while my development machine was in the shop. I love using a Unix command line and tools such as ZSH and Oh-my-zsh!. In my day job, I have to use Ruby and Node on a regular basis, and I love using iTerm2 as my main terminal emulator. I also primarily use desktop tools like Visual Studio Code, Docker, and Slack.
One option would be to simply install Docker and set up a containerized development environment, but that would be too easy.
Could I continue using my normal development tools and my workflow without my MacBook? I set out to find out!
"Learn how to install Windows Subsystem for Linux, turning your Windows 10 machine into a full-blown Linux powerhouse"
For my main development and blog writing activities, I primarily use Git, Ruby and NodeJS. Fortunately, there are Windows installers for all of these that ultimately work, but they all feel a bit Windows-y. For example, the best way to use Git on Windows is to use Git for Windows, which provides a Git Bash application that drops you into a terminal running Git. Or you can use a desktop application like GitHub Desktop, or the built-in Git interface inside Visual Studio Code.
As for Ruby, I enjoy using RVM, which makes the installation and management of different Ruby versions very easy and relatively painless. Windows is supported using something like Cygwin, but again it's not really a native solution and I ran into issues getting it to work the way I'm used to.
All of these are good solutions (if you can get them working) but seeing as the goal of this exercise is to figure out a way to work just like I have been doing on my MacBook, I wanted to explore further.
I really enjoy using the terminal for the speed and ability to get things done concisely and quickly. Using a terminal that supports features such as tabs, horizontal and vertical splitting, and Unix command utilities and features like piping and output redirection is very important to me.
Unfortunately, this is where Windows starts to break down. Windows has Command Prompt, which doesn't support any of those nice UI features that I like, and with me not being familiar with Windows shell script, I find it cumbersome. There is also Powershell and, as the name suggests, is very powerful but it's something new I'd have to learn. Ultimately, it would take time until I'm as productive as before. Interestingly for the Powershell users, posh-git gives you adornments in the terminal as the Git status of the current folder, which is one of the features I like about Oh-my-zsh.
I'm in love with iTerm2 on the Mac for its ability to use tabs, split windows, profiles, and theming, so is there anything that gets me close?
Hyper is a terminal emulator that supports at least the UI features of being able to use tabs and window splitting. It's based on Electron and so is cross-platform, and supports more advanced features like themes and plugins. I do like theming my applications so that they look more pleasing to the eye, but I was willing to forget about that for this short-lived exercise.
However, it's just an emulator and therefore is still just using Windows shell script. Something more fundamental under the hood would have to change.
Windows Subsystem for Linux (WSL) is a way to run native Linux commands and tools alongside your existing Windows apps. It doesn't use a virtual machine and is as easy to access as opening a terminal window. To quote directly from the documentation:
The Windows Subsystem for Linux lets developers run GNU/Linux environment -- including most command-line tools, utilities, and applications -- directly on Windows, unmodified, without the overhead of a virtual machine.
Sounds good, doesn't it? In theory, I should be able to use all the command-line tools that I'm used to without leaving my Windows desktop environment.
To install WSL, you need to be on the Windows 10 Fall Creator's Update (build 16215). Then, you can install the feature by using the "Turn Windows features on or off" facility and ticking "Windows Subsystem for Linux":
It can also be installed by running this Powershell command:
# Run this inside Powershell to enable the WSL feature Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux
Note: The machine may need to be restarted once WSL is installed
One of the many Linux distributions on the Windows Store can then be installed as a Windows App. I chose Ubuntu as it's the one I'm most familiar with. An Ubuntu app becomes available once it's installed, but the normal Windows Command Prompt app can be used in its place if you so wish.
Then, to enter a Linux terminal, open Command Prompt (or your terminal emulator of choice) and type
wsl to get started. The next thing you will see is your Linux command prompt.
# My WSL command prompt inside the Command Prompt application /c/Users/steve >
So what can be done from here? Supposedly anything that can normally be done from an Ubuntu terminal. Let's check what release of Ubuntu I'm using:
> lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.2 LTS Release: 18.04 Codename: bionic
> curl -i google.com HTTP/1.1 301 Moved Permanently Location: http://www.google.com/ Content-Type: text/html; charset=UTF-8 Date: Tue, 26 Feb 2019 10:42:51 GMT Expires: Thu, 28 Mar 2019 10:42:51 GMT Cache-Control: public, max-age=2592000 Server: gws Content-Length: 219 X-XSS-Protection: 1; mode=block X-Frame-Options: SAMEORIGIN
> sudo apt-get install vim Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libfreetype6 Use 'sudo apt autoremove' to remove it. 0 upgraded, 0 newly installed, 1 reinstalled, 0 to remove and 3 not upgraded. Need to get 1152 kB of archives. After this operation, 0 B of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu bionic/main amd64 vim amd64 2:8.0.1453-1ubuntu1 [1152 kB] Fetched 1152 kB in 0s (2468 kB/s) (Reading database ... 39405 files and directories currently installed.) Preparing to unpack .../vim_2%3a8.0.1453-1ubuntu1_amd64.deb ... Unpacking vim (2:8.0.1453-1ubuntu1) over (2:8.0.1453-1ubuntu1) ... Setting up vim (2:8.0.1453-1ubuntu1) ...
As you can see,
apt-get is available and can be used to install any software that would normally be available on a native instance of Ubuntu.
Can something like NVM be installed the same way as on a native Linux distribution?
For the purposes of this recording and in the interest of time, I had already installed NVM on this machine, but not Node itself. Take a look and see what happens!
Thankfully, nothing unremarkable happens! I get Node 10 and NPM installed just as happily as I would have done on a native Ubuntu install. I can also confirm that I was able to install RVM perfectly well, by following the installation instructions that I would have normally followed on Linux.
Furthermore, I was able to install ZSH and Oh-my-zsh without any issues, again using the instructions provided for Linux. With this in place, I'm already most of the way towards working the way I'm used to on my Macbook!
Now that I have the tools installed, what is the actual development experience like?
I can happily report that it is fairly unintrusive to the point where I almost forget I'm working on a Windows machine. Thanks to the fact that Windows drives are automatically mounted into your Linux environment, I still get access to my files and folders from within my Ubuntu environment. This means I can use Git and all the other command-line utilities that I'm used to, but still manipulate those files using whatever editor on the host Windows machine I want. By default, your host drives are available in the
/mnt folder. So a Windows path of
D:\Development\auth0 would be available in your Linux environment as
At the moment, it's not possible to get access to the Linux filesystem from the Windows host, but that will change in Windows 10 build 1903. In a nutshell, WSL will start a 9P file server on bootup with Windows as the client, serving Linux files over an internal network protocol.
Windows UI features
For me, the operating system shell is just as part a part of the development experience as the software I use to do my job. For example, I'm a heavy user of OSX's Spotlight feature, and I regularly navigate through my operating system simply by using text search; it's very easy to press
Cmd+Space and search for what I want.
Windows 10 supports just the same functionality and allows me to move around the operating system very easily, opening programs and manipulating windows simply by using the keyboard. Pressing
Windows Key opens the Windows Start Menu, where I can just start typing what I want. Admittedly this is not obvious, as there is no focussed text box to indicate to the user that they're able to type a search term.
Another feature of OSX that I often use is multiple desktops, or Spaces. This is part of the Mission Control feature that can partition applications into different Spaces, allowing you to easily swipe between them. I use this feature to organize my work better. As an example, with every instance of Visual Studio Code that I have open, I tend to have a corresponding instance of iTerm2 open at my working directory for the project I'm working on. Using multiple desktops, I can group these instances together so that I have different desktops set up for different projects. I can switch between different desktops using a trackpad gesture, or by using
Ctrl+Left/Right Arrow to move between them.
Luckily for me, Windows 10 supports this exact feature! Just like on OSX, different desktops can be created that play host to different instances of running applications, and I can switch between them using simple keyboard commands. Pressing
Win Key+Tab gives me a Mission Control-like overview of my available desktops and applications. I can even specify that an instance of an app is available across all my desktops (it's handy to have my favorite music player available wherever I need it!).
"With WSL, I love that I have all the command-line tools that I'm used to available to me, as well as the ability to use multiple desktops, search, and use all my favorite desktop applications."
A word about Docker
I wanted to touch on my experience using Docker with this setup. I already have Docker Desktop installed on my host Windows machine, and I was concerned that I may have had to uninstall that in order to get it working inside WSL. Either that, or I would have to live with having two instances of Docker on my machine taking up valuable hard-drive space; one for the Windows host, and another inside WSL.
Thankfully, I didn't have to do either of those things and following these instructions on setting Docker up to work on WSL (flawlessly, as the article title puts it) was very easy and painless. The basic principle is that Docker running on the Windows host can also be used by the Docker client running inside WSL, as the two are interfaced by a REST API. The key piece of configuration is to tell the Docker client inside WSL where the host is. By default, it connects to a Docker instance running on the same machine, but in this case, we can point it to the instance running on the Windows host.
After having gone through the setup myself, I can confirm that Docker from inside WSL works as expected!
As you might expect from reading through this post, generating SSH keys works exactly the same way as on any other Linux distro. I followed the SSH key guide on GitHub.com and it just works. The caveat is that the SSH key will be generated for your WSL install, and so the key will need to be added to any services you use that require SSH keys.
This is fine for me, but if you already have an SSH key for your Windows profile then you can symlink your
.ssh folder into your WSL install if you wish to use the same keys.
I haven't actually sold my Macbook. However, given everything that I've experienced getting my development environment pretty close to what I'm used to, I'm pretty certain that I would be able to live without it for a while longer. I love that I have all the command-line tools that I'm used to available to me, as well as the ability to use multiple desktops, search, and use all my favorite desktop applications.
So far I haven't found an instance where Windows Subsystem for Linux has provided an obstacle where I can't get working, although I admit that even the use-case I present here is probably quite simplistic compared to how some other people would like to use it.
Auth0, a global leader in Identity-as-a-Service (IDaaS), provides thousands of customers in every market sector with the only identity solution they need for their web, mobile, IoT, and internal applications. Its extensible platform seamlessly authenticates and secures more than 2.5 billion logins per month, making it loved by developers and trusted by global enterprises. The company's U.S. headquarters in Bellevue, WA, and additional offices in Buenos Aires, London, Tokyo, and Sydney, support its global customers that are located in 70+ countries.