Table of Contents

Windows Subsystem for Linux

A Unix-like OS (Linux, BSD, MacOS) is by far the best environment for software development. If you do not have a real Unix-like OS then you almost certainly have Windows. Several options exist to obtain a Unix-like environment within Windows, and Windows Subsystem for Linux (WSL) is by far the best of them (with certain reservations [Note 1]). With version 2 of WSL you can obtain a seamless Unix-like development experience, including a real Unix desktop.

Installing WSL2

Many online guides exist, mostly all saying the same thing. Pick any of them. e.g: http://https://www.omgubuntu.co.uk/how-to-install-wsl2-on-windows-10

After installation you can choose between several Linux distributions. Ubuntu is often recommended. I personally prefer Debian with the xfce4 desktop and the rest of this document assumes that environment.

Installing a desktop

Unix desktop

Using the Linux desktop offers many advantages over the default WSL command-line experience, including:

Running a Linux desktop on Windows requires two things: (1) a window server to display the desktop content, and (2) the desktop window manager and associated applications.

The window server is a native Windows application that displays the Linux desktop in a big Windows window. The desktop window manager and associated applications are native Linux programs installed in the Linux system. The two communicate over a network connection, and don't even have to be running on the same computer.

Installing the X server for Windows

Unix-like operating systems use the X11 Window System (often abbreviated X11, or just 'X'). In X the GUI windows are displayed by a server running on your local computer, with any number of client programs connecting to that server to display their graphical content. Several implementations of the X server for Windows are available. The only one that works completely reliably for me is VcXsrv. Install it like any other Windows application after downloading it from here: https://sourceforge.net/projects/vcxsrv

Installing the desktop for Linux

The meta package xfce4 installs everything needed for the Linux desktop. Start a WSL command line and then install the desktop with the apt install command like this:

$ sudo apt install xfce4

Setting up the desktop environment

For the best Linux desktop experience you should start a few services along with the desktop. I recommend doing this using a script because (1) the entire desktop can then be started by typing one simple command that runs the script, and (2) it lets you easily create a clickable Linux desktop launcher that can be pinned to the Windows task bar.

I usually put my own scripts and programs in a directory called bin directly below my home directory.

$ cd
$ pwd
/home/piumarta
$ mkdir bin
The bin/startx script

In my bin directory I create a script called startx that sets up the environment for the X server and desktop, and then starts them both. The contents are shown and described below, and you can download the file here: startx

#!/bin/sh

set -e
set -x

exec > /tmp/startx.log 2>&1

export DISPLAY=$(awk '/nameserver / {print $2; exit}' /etc/resolv.conf 2>/dev/null):0
export SHELL=/bin/bash

cd "$HOME"

/mnt/c/Program\ Files/VcXsrv/vcxsrv.exe :0 -ac +bs -dpi auto -dpms r -wgl $OPTIONS &
sleep 1
dbus-launch --exit-with-session "$HOME/.xsession"

The first line says that this file is a shell script. The two set commands say to exit at the first sign of trouble and to print each command as it is executed. The exec command sends all output, including error messages, to the file /tmp/startx.log. The DISPLAY variable is set so that client programs know how to contact the server, using the IP address for the Linux session that WSL sets up for us in the /etc/resolv.conf file. The SHELL variable is set to the preferred shell, which is bash. The cd "$HOME" command makes sure the working directory for the desktop session is your home directory, so that the behaviour is consistent no matter which directory is current when you run the startx script. The next line launches the VcXsrv X server from its location in the Windows filesystem on the C drive. The options do the following:

The sleep command pauses for one second to give the X server time to start up. The final dbus-launch command starts a software communication service that many Unix programs and X clients use, and then runs another script called .xsession in your home directory to set up and start the Linux desktop window manager.

After creating or downloading the file, make sure it has execute permission:

chmod +x bin/startx
The .xsession script

The file .xsession (in your home directory) contains a series of commands that set up the desktop environment and then run the desktop window manager. The contents are shown and described below, and you can download the file here: .xsession

#!/bin/bash

test -e .Xauthority || touch .Xauthority
test -e .Xdefaults  || touch .Xdefaults

xrdb -merge .Xdefaults &

export RUNLEVEL=3
export OOO_FORCE_DESKTOP=gnome

export LANG="en_US.UTF-8"
export LC_ALL="en_US.UTF-8"
export LANGUAGE="en_US.UTF-8"
export LC_CTYPE="en_US.UTF-8"

xset r rate 200 50

exec startxfce4

The first two lines of test and touch commands ensure that the files .Xauthority (which proves to the X server that you started it) and .Xdefaults (which contains the initial X resource database) are present, and creates empty versions of them if necessary. The xrdb command loads some default settings for X client programs from the .Xdefaults file. The RUNLEVEL variable is set to tell any program that cares that the WSL session is just like a normal login session on a physical Linux computer. The OOO variable is set to make Libre Office display nicely on the xfce4 desktop. The four LANG* and LC_* variables are set to tell programs to use UTF-8 encoding and English messages. The xset command sets the keyboard repeat delay to 200 milliseconds and repeat rate to 50 per second. (I set auto repeat to be super-fast to make it easy to navigate source code in text editors; modify these numbers if it is too fast for you.)

After creating or downloading the file, make sure it has execute permission:

chmod +x .xsession
The .Xdefaults file

Settings for X applications are kept in a database, similar to the registry that Windows uses to store settings, called the X resource database. It is created when the Linux desktop starts. The .xsession script above loads your initial X database settings from a file called .Xdefaults (in your home directory). I recommend you add some settings to that file to make some important programs work better.

The contents of my .Xdefaults file are shown and described below, and you can download the file here: .Xdefaults

Emacs.menuBar:				0
Emacs.toolBar:				0
Emacs.verticalScrollBars:		off
emacs*Foreground:			Wheat
emacs*Background:			DarkSlateGray
emacs.pane.menubar.margin:		0
emacs*scrollBarWidth:			12
emacs*cursorColor:			#e02020
!
xterm*metaSendsEscape:			true
xterm*eightBitInput:			true
xterm*saveLines:			2000
xterm*wm_option.autoRaise:		on
xterm*wm_option.gadgets:		on
xterm*wm_option.title:			on
xterm*background:			beige
xterm*foreground:			black
xterm*colorBDMode:			false
xterm*sunFunctionKeys:			false
xterm*jumpScroll:			true
xterm*scrollBar:			false
xterm*charClass:			33:48,37:48,45-47:48,58:48,64:48,126:48
xterm*borderColor:			black
xterm.waitforwm:			false
xterm*fontMenu.Label:			VT Fonts
xterm*fontMenu*fontdefault*Label:	Default
xterm*fontMenu*fontdefault:		-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso8859-1
xterm*fontMenu*font1*Label:		Unreadable
xterm*VT100*font1:			nil2
xterm*fontMenu*font2*Label:		Tiny
xterm*VT100*font2:			-schumacher-clean-medium-r-normal--8-*-*-*-c-50-*-*
xterm*fontMenu*font3*Label:		Small
xterm*VT100*font3:			-schumacher-clean-medium-r-normal--10-100-75-75-c-60-iso646.1991-irv
xterm*fontMenu*font4*Label:		Medium
xterm*VT100*font4:			9x15
xterm*fontMenu*font5*Label:		Large
xterm*VT100*font5:			10x20
xterm*fontMenu*font6*Label:		Huge
xterm*VT100*font6:			lucidasanstypewriter-bold-24
XTerm.VT100.faceSize1:			6
XTerm.VT100.faceSize2:			8
XTerm.VT100.faceSize3:			10
XTerm.VT100.faceSize4:			14
XTerm.VT100.faceSize5:			20
XTerm.VT100.faceSize6:			28
xterm*fontMenu*fontescape*Label:	Escape Sequence
xterm*fontMenu*fontsel*Label:		Selection

The first group of settings streamlines the look of Emacs by removing the scroll bar, menu bar, and tool bar. They also tell Emacs to use the classic Debian colours that I find pleasant and relaxing to look at for long periods. The second set of settings tell the default X terminal emulator xterm how to handle the meta key (so that Emacs-like cursor movement shortcuts work in the terminal too), what colours to use (again so that they are not tiring to look at for extended periods of use), which fonts to use for different sized text, and over which set of characters to extend the selection when double-clicking on text.

Starting and stopping the desktop

You should now be able to open a WSL Debian terminal and type

bin/startx

to start an xfce4 Linux desktop session.

When stopping the session I always like to log out (of the Linux desktop session) first by clicking either on the 'Applications' menu (top left) or my name (top right) and selecting 'log out'. That way I am certain all my window manager settings are properly saved for the next session. Logging out will not actually stop the X server; to do that, press the 'close' button on the VcXsrv Windows window and then click on 'Exit' in the pop-up confirmation dialogue that appears.

Making a Windows (task bar or desktop) launcher for the Linux desktop

First locate the Windows program that launches your Linux distribution. This is easy to do using the Windows PowerShell get-command function. Start PowerShell and then run this command:

PS C:\Users\piumarta> (get-command debian.exe).path
C:\Users\piumarta\AppData\Local\Microsoft\WindowsApps\debian.exe

Open that file's location in Windows Explorer

PS C:\Users\piumarta> cd .\AppData\Local\Microsoft\WindowsApps
PS C:\Users\piumarta\AppData\Local\Microsoft\WindowsApps> explorer.exe

and then create a desktop shortcut by right-clicking on the debian.exe file and selecting 'Send to > Desktop (create shortcut)'.

Right-click on the desktop shortcut that was just created and select 'Properties'. Activate the 'Shortcut' tab and then edit the 'Target' field to add the following items after debian.exe:

run /bin/bash -c /home/piumarta/bin/startx

(but, obviously, replace 'piumarta' with your own account name).

Your entire 'Target' field for the shortcut should look something like this

C:\Users\piumarta\AppData\Local\Microsoft\WindowsApps\debian.exe run /bin/bash -c /home/piumarta/bin/startx

(with your account name instead of mine). Click on Apply and then OK.

Double-clicking the shortcut (or right-clicking it and selecting Open) should then start your Linux desktop. You can drag this shortcut to your task bar, and on mine I replace the icon with the one embedded in the VcXsrv executable to give the shortcut an appropriate appearance.

Notes

  1. One 'certain reservation' about WSL being the ideal environment is that you will lose your entire Linux desktop session at random times when Windows unilaterally decides to reboot your computer overnight, without permission, to install an update that you probably did not even want. If this is a 'deal breaker' for you then you can either write a script to 'slide' your 'working hours' forward once an hour (preventing Windows from ever rebooting without permission) which has its own drawbacks, or adopt the the next best option as your new best option: install both Windows and a 'real' Linux distribution as guest operating systems under the same hypervisor, and then use x11vnc on the Linux guest to allow Windows to connect to a persistent Linux desktop. (If you care about 3D performance in Windows you can also 'pass through' your entire GPU to Windows and obtain native graphics performance.) The Linux desktop user experience with this option is almost identical to the native WSL2 experience, with the advantage that Windows rebooting itself will not in any way affect your Linux desktop.

    I have exactly this setup on my main computer at home, using the Proxmox hypervisor, and it works perfectly (including PCI pass-through of my NVIDIA GPU to Windows). The procedure to set this up is a little more complex than setting up WSL2 and xfce4, and is definitely beyond the scope of this short how-to.