Monday, July 15, 2019

Diagnosing and Fixing WSL initialization issues

After uninstalling ZSH from my Ubuntu WSL instance, my system wouldn't start. How to fix it? Let's take a look.

I was recently testing the ZSH shell on my WSL instance and decided to make it default. After removing it with Apt my WSL instance suddenly wouldn't start up. After investigating, I realized that WSL was failing to start a session for my user using a now nonexistent ZSH shell. Strangely enough, Apt/Ubuntu ignored that my system still had references to that shell. My expectation is that it would have reverted the user sessions back to bash what didn't happen.

In case you're interested, here's how to reproduce the error:

  1. Install a new shell to your user (ex. zsh)
  2. Set it to your default (for example by using chsh but the zsh install script already does so)
  3. Uninstall that shell
But before we jump to the solution, it's important to understand some how WSL works in the background.

WSL Background

WSL is run by Windows as the wsl.exe executable file located on c:\windows\system32. That executable bootstraps the whole Linux subsystem on your machine using files located on your Windows disk. Knowing where the files used by your WSL instance are located is a good start to troubleshooting. On my machine, they're found on:
C:\Users\<my-user>\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_79rhkp1fndgsc\LocalState\rootfs
On yours, it could be equal or very similar. Definitely on your user's AppData\Local\Packages folder.

Fixing the Issue

Because wsl.exe is an executable, we can run it on the console. In order to do so, open a windows terminal and:
  1. cd into c:\windows\system32 
  2. run wsl --help 
You should then see a generic help for your instance:
However if WSL is broken any additional information will not be output on the console. So, it's important to have some context on the issue before we can fix it. On my particular case, since I knew my default shell (ZSH) was failing to load, to fix the issue I just had to change my user's shell to bash as the root user. That's as simple as:
  1. log in WSL as root
  2. As root, use chsh to change your user's shell

Logging in as Root from the Terminal in WSL

To login as root from the terminal, simply run the following command:
C:\Windows\System32>wsl -u root

Changing the User shell with chsh

Next we change the shell using chsh. chsh is a GNU utility created to chang the user shell. After logged in as root, one simply has to run the command:
chsh -s /bin/bash bruno

Testing

To test, you either have to close WSL (^D) and reopen it or as root, ron run su <user> on the current shell:
su bruno

Final Thoughts

Despite WSL not emitting much information on failures, it's important to remember that there's still a Linux system behind it. Knowing Linux or searching Linux related articles could help.It's also important to remember that, because all the filesystem is located on your C drive, you still have access to logs/config files and could try to fix from there if necessary.

References

See Also

For more posts about WSL on this blog, please click here.

Monday, July 1, 2019

How to create a Ubuntu Desktop on Azure

We have multiple Linux offerings on Azure for the server but none for the desktop. How can we build one hassle-free?

Photo by XPS on Unsplash

Azure offers a variety of Linux servers including RHEL, CentOS, Debian and Ubuntu. But no desktop. As developers, it would be nice to have access to a development VM on the cloud with a GUI and software like Visual Studio Code and Chrome.

On this post, let's see how to install the necessary software to transform an Ubuntu server into a functional Ubuntu desktop including the necessary procedures to RDP into it from Windows, Mac and Linux.

What we will do

On this tutorial we will install the following tools:
If you need Visual Studio Code, please follow this tutorial.

Creating the Instance

The base image for our desktop will be Ubuntu Server 18.04 LTS. As this is a server image, it doesn't contain a GUI. We will install it ourselves as long as a browser and a tool to connect remotely via RDP. By default we can connect to it via SSH using our WSL or Putty. In Azure, click "Create a Resource" then select Ubuntu Server 18.04 LTS.

When this post was created 18.04 was the last LTS but now we have 20.04. Feel free to use it if you prefer. The steps are exactly the same!

Configuring the VM

Now let's configure the VM. Here we will set the username, password, VM name, resource group, region, etc that are adequate to you. For example, my configuration is show below:

Setting up Disks

The next step is disk setup. I selected Premium SSD with 10GB as seen below:

Setting up the Network

For the network interface, I created a new VNet/Subnet and requested a new IP. Note that the IP will only be available to us after creation. You also need to open inbound ports for SSH (22) and RDP (3389) as we'll need them later to access our instance remotely later: 

Review and Create

Review and if everything's correct, click on Create to proceed:
After a couple of minutes the instance should be created and running.

Connecting to our Instance

Once our instance is deployed, let's connect to it. Depending on how you configured during creation, it can be accessed via username/password or via SSH. You should use Azure's overview window to get important information as IP address and username.

To access it, click the Connect tab from where you should see:

Because I configured ssh and uploaded my ssh key, I simply have to open my WSL and enter the following command:
# connect to my remote server using ssh
ssh bruno@<my-ip>
This is the output of my first connection to that VM:
If you chose to provide an username/password during creation, you're still good to connect via SSH. The only difference is that you'll have to provide your password upon connection.

Diagnosing Connection Issues

If for some reason you get:

ssh: connect to host 13.66.228.253 port 22: Resource temporarily unavailable
it's because the port 22 (SSH) is not open for connection externally. And that's a good thing! It pretty much tells us that our connection is being blocked by a firewall. By default in Azure, VMs are wrapped into a Network Service Group (NSG) which is an extra layer of protection to our cloud artifacts. It basically provides full control over traffic that ingresses or egresses a virtual machine in a VNet.

In order to expose that port, click on the Networking tab to change the inbound rules:
To add a new one, we click the Add inbound port rule button and enter the rule as below:

Security Considerations

Please note that it's recommended that you only expose ports that are essentially necessary to to security threats. In our example, we should only expose ports 22 (SSH) and 3389 (RDP). It's also recommended to configure your NSG to restrict access to your IP only.

Once that's done, try to connect again with:

# connect to my remote server using SSH
ssh bruno@<my-ip>

Installing the Required Tools

With the VM up and running and with SSH access to it, it's time to install the required tools to make our server more user friendly. Remember, we'll have to install a desktop manager, some CLI tools and Firefox.

Updating the system

The first thing to do should be updating the system and the list of packages available to your Ubuntu instance with:
# Updating the package Sources
sudo apt update && sudo apt upgrade -y

Installing the CLI tools

The next step is to install useful CLI tools to work (some of them are already pre-installed with the Azure/Ubuntu image):
# install basic terminal tools
sudo apt install tmux git ranger vim

Installing LXDE

Now, let's install our desktop (LXDE). The good news is that Canonical, the good folks behind Ubuntu, already provide a metapackage called lubuntu-desktop that contains not only LXDE but Firefox and other very useful GNOME tools. We install it using the following command:
sudo apt install lubuntu-desktop -y
Please note that this installation take a while as ~2GB of files have to be downloaded and installed on your server.

Setting up Xrdp

The last and final step is to install Xrdp. As previously mentioned, this tool is required to connect to our instance using RDP. This installation downloads ~8Mb and runs very quickly after the above commands. Type the following on the shell:
# install xrdp
sudo apt install xrdp -y
Next step is to start the xrdp service so we can connect to it via RDP.
# start the xrdp service
sudo systemctl start xrdp

Connecting via RDP

All should be good to go now so let's try to connect to our machine. Simply enter the IP address on the RDP information and hit connect. On mine, I got the prompt:
Note that if when creating your VM on Azure you selected SSH, you have to setup a new password for your user. This is done with:
# setting up a new password for our user
sudo passwd bruno

LXDE 

If you enter your password correctly, you should login to your LXDE session. This is my awesome LXDE session running on Azure. By clicking on the blue icon above you'll have access to all the software included with the metapackage:

Persisting Changes

What happens after a reboot? Will the VM still run Xrdp? No. Unless we make the service permanent. If that's what you want, do that by running the below command on the terminal:
# permanently enable the Xrdp service during boot
sudo systemctl enable xrdp

Final Thoughts

The cloud is an awesome environment to test new things out. On this example I used Azure but you could reproduce pretty much everything here on your cloud provider of choice. It's also important to remember that two of the most fundamental aspects of a Linux system are customization and extensibility. So, installing/changing a GUI, trying out different software, adding/removing repos, etc should be simple on the cloud as is on a local VM. And that shouldn't prevent us from being creative and using our imagination.

I encourage you to play with Azure or your preferred cloud provider and experiment not only with a Ubuntu Linux VM but other operating systems. It's all a few clicks away and a fantastic learning experience!

References

See Also

About the Author

Bruno Hildenbrand