Article / 19th Jun 2017

Developing on Windows

I've been developing on Windows as my primary platform for about the last year and a half (and getting puzzled looks at conferences for about that long). I'm often asked how (or why) I do it, so as I've recently bought a new Surface Pro, here's my brief guide to developing (with Python) on Windows.

Background

I've been a Linux user since around 2004, using Red Hat, Gentoo, Debian and Ubuntu over the years. I still have a Linux laptop at work as my primary development machine; I enjoy Linux on the desktop a lot, and it took quite a bit to get me to change.

The main thing that changed in the Windows world was the introduction of the Windows Subsystem for Linux (WSL), sometimes also called "Bash on Ubuntu on Windows". WSL is a rather impressive piece of kernel engineering that allows Windows to natively run Linux applications - no virtual machines, no emulation, just a different frontend on the NT kernel. You can open the Windows Task Manager and just see bash or git right in there.

WSL brings you a complete Ubuntu userland, complete with apt-get, access to the Windows drive, and near-complete compatability with Linux ABIs (it even supports mmap and UNIX semaphores). This solved the missing piece of running either Windows or Mac for me prevously - substandard command line interfaces that forced you to run virtual machines for any development.

As for why I moved away from Ubuntu, it's a combination of bad support for pen, touch and compact hardware (like the Surface Pro), and poor support for high-end tools like Unity 3D and Adobe Premiere. Neither of these are issues at work, so I still run Ubuntu there.

The Windows (and especially Surface) ecosystem has come a long way, and the fact that I can click the end of the pen, OneNote pops open, and I can get to writing notes immediately is just one example of the integration and feature set that has me sold on those devices. Don't get me started on how the Surface Dock is finally a good laptop docking solution after trying about a decade of other options.

Hardware

The biggest complaint people often have going into the Windows ecosystem is how bad the hardware is. There's a lot of bad hardware out there, for sure, and everyone and their dog will try to sell you a Windows laptop with lots of weird stuff preinstalled.

There is, however, a subset of very good hardware, and that subset still spans a range of form factors that Apple just don't have pinned down yet, while being equivalent in build quality.

Here's my recommended list of hardware right now (June 2017):

There are other options, of course, including building your own desktop if you like that kind of thing (I do sometimes), but these are good, standard ones I can personally recommend. In particular, it's hard to go wrong with Microsoft hardware - the Surface Laptop and Surface Studio are also lovely, they just don't fill niches that I need.

Even better, if you live in a country with a physical Microsoft Store, their support is excellent and if you have a problem (or if you accidentally drop it and get the "Microsoft Complete" extended warranty), they'll swap it on the spot, sometimes even giving you the new model if the old one is no longer in production.

Setting Up

OK, so let's walk through how to set a Windows machine up for development in the way I like (and also point out a few of the things I fix with Windows along the way). Windows 10 is a good OS generally - it's fast, stable, and good at things like resolution scaling - but it has a few places where overzealous product design shoves ads in your face until you turn them off.

The process starts when you open a new PC and go through the first-time setup process. This has changed a little over the years, and currently features an over-enthusiastic Cortana talking to you (you can turn her off), but the basic things you need to do are the same:

Once first-time set up finishes, there's a few more of the ad options to turn off and then Windows will be entirely ad-free:

The last thing to do is to make sure BitLocker is enabled. Right click on the C: drive in Explorer and select "Manage BitLocker"; if it's not on, you probably want to enable it. On any recent machine it uses processor extensions for the encryption so it has very little overhead. Make sure you back up the key, though!

Package Management

The one downside of Windows compared to most Linux distributions is centralised package management; downloading endless installers is not fun. Thankfully, most of this can be achieved by using Chocolatey, which is a Windows package manager and handles installation and updates of most things. You can install programs with one command:

choco install vlc

And update them all in one go:

cup all

It can't handle everything, but most of the things it doesn't handle have their own updaters (in my case, the Adobe suite, Google Chrome, and Steam).

By default it will ask you to confirm installing every package, which can get tedious; I genenerally run this to turn that off:

choco feature enable -n allowGlobalConfirmation

You should always run it from an elevated command prompt, which if you're not familiar with Windows, you can just get by right clicking on the Start button and selecting either "Command Prompt (Admin)" or "PowerShell (Admin)", or using ConEmu as I cover below.

If you're moving from a previous Windows install, you can list what you installed in the previous Chocolatey install (and what's on the system not from Chocolatey) using:

choco list --localonly ---includeprograms

I save this to a text file and use it to know what to install on my new machine.

WSL

It's time to install WSL. I recommend you follow the official installation guide; just be aware that you will need a reboot after installing the WSL feature.

I also tend to add Hyper-V support when I'm in the Add/Remove Windows Features menu, so I can get it all done in one reboot and so I don't need to do it later when installing Docker for Windows.

Once the installation is complete, open the "Bash" application (hit the Windows key, type "bash", hit enter), and follow the instructions for a first-time setup. Once that's complete, you'll have a working Linux environment; you can apt-get install whatever you need, and this is where I usually link in things from the Windows folders (located under /mnt/c).

Note that you can access Windows files from Linux but not the other way around, so I usually host all my development files in my Windows user directory and then symlink it inside of Linux into the Linux home directory.

Once I'm done installing WSL I'll run a huge apt-get install of all the stuff I normally use (python, virtualenv, etc.), and then I can just get working. Since it's still native Windows under the hood, any servers you run here just appear on "localhost" and you can talk between apps on both the Win32 and Linux subsystems; I run the Microsoft-maintained Redis as a Windows service, for example, but WSL still sees it as locahost:6379. Docker setup is covered below.

The shell that WSL comes with is a bit basic, though, so let's install a better one and improve some other aspects of the Windows experience.

ConEmu

ConEmu is my preferred terminal program on Windows; it provides the feature I've used for many years, starting with yakuake on KDE, which is that it pops down from the top of the screen when you hit a hot-key (in my case, F12).

We can just use Chocolatey to install it:

choco install conemu

On first boot, you will get a small settings screen, but don't be fooled; the main settings screen ranks up there for having the most options and sub-options imaginable. Whatever you want to do, it's probably in here; apart from the Quake-style options, I usually change it so that the Ubuntu shell is the default shell for new tabs and change some of the keyboard shortcuts.

AquaSnap

Windows actually comes with some basic shortcuts for window tiling in the form of Win+Left and Win+Right, which snap windows to half the screen on the left and the right. I like a bit more flexibility, though, and so I use AquaSnap, which as well as having tiling options also does nice things like making windows transparent when you drag them and snapping them to each other.

Docker

The other key thing I use, and that can be a bit tricky, is getting Docker working. WSL does not yet natively support the namespacing needed to run Docker, so you need to use Docker for Windows, which uses a virtual machine to do everything (though it's wrapped up in a nice, easy-to-use way).

You can install Docker for Windows from the Docker site, and just follow the setup instructions to get it booted. This will install the Docker client and tools on Windows shells (cmd, powershell), but not inside WSL - there's a few more steps for that.

First, install the Docker tools inside the WSL Ubuntu environment:

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"
sudo apt-get update
sudo apt-get install docker-ce

Now, you'll need to set environment variables so Docker talks over TCP rather than trying to use a UNIX socket. Unfortunately, I have not yet found out where the client certs are for Docker for Windows, so I have to set an unsecure connection using this environment variable:

DOCKER_HOST=tcp://127.0.0.1:2375

And then, to make Docker listen on this port, select "General" > "Expose Docker without TLS" inside the Docker for Windows settings.

Next Steps

That's it for my basic setup; there are things particular to me, like my editor (Sublime Text) or my file sync solution (Syncthing) that I also install, but pretty much everything is available on Windows anyway so you have plenty of choice.

I'll leave you with a couple more tips in case you are not too familiar with modern Windows, that make it much more streamlined for me: