Ubuntu 20.04 — Some Azure Annoyances

Brian Richardson
6 min readJun 18, 2021

Ubuntu 20.04 has given me some issues on Azure. Previously, I’d installed 18.04 and upgraded to 20.04 with do-release-upgrade. This mostly seemed to work though it is obviously the long way round. A couple weeks ago the 20.04 image made its way to the top of the Marketplace for Compute. So I installed one to give it a test drive. Surprisingly, it was filled with a number of pitfalls.

  1. Python2 isn’t installed, so LinuxDiagnostic extension doesn’t install. This seems to cause the deployment to fail, but the VM is running by this point.
  2. NetworkManager is no longer the default renderer for netplan. And netplan’s configuration is now managed by cloud-init and messing with it seems to brick the machine.
  3. eth0 seems to have some kind of “shadow”, an interface with a different name (which is different every boot!), the same MAC address, and no IP.
  4. (this is an old one, but I’ll throw it in because it’s annoying) Connecting via xRDP causes the “Authentication is Required to Create a Color Managed Device” dialog for each monitor you have in the remote session.
  5. Sound doesn’t work and the pulseaudio installers are missing in 20.04

LinuxDiagnostic Extension

Once you login to the machine by SSH, you can install the extension manually after installing python2 and running the following command:

sudo update-alternatives — install /usr/bin/python python /usr/bin/python2 1

The extension can be installed with the following script:

# Set your Azure VM diagnostic variables.
my_resource_group=…
my_linux_vm=…
my_diagnostic_storage_account=…

# Login to Azure before you do anything else.
az login — tenant xxx

# Select the subscription that contains the storage account.
az account set — subscription xxx

# Enable system-assigned identity on the existing VM.
az vm identity assign -g $my_resource_group -n $my_linux_vm

# Download the sample public settings. (You could also use curl or any web browser.)
wget https://raw.githubusercontent.com/Azure/azure-linux-extensions/master/Diagnostic/tests/lad_2_3_compatible_portal_pub_settings.json -O portal_public_settings.json

# Build the VM resource ID. Replace the storage account name and resource ID in the public settings.
my_vm_resource_id=$(az vm show -g $my_resource_group -n $my_linux_vm — query “id” -o tsv)
sed -i “s#__DIAGNOSTIC_STORAGE_ACCOUNT__#$my_diagnostic_storage_account#g” portal_public_settings.json
sed -i “s#__VM_RESOURCE_ID__#$my_vm_resource_id#g” portal_public_settings.json

# Build the protected settings (storage account SAS token).
my_diagnostic_storage_account_sastoken=$(az storage account generate-sas — account-name $my_diagnostic_storage_account — expiry 2037–12–31T23:59:00Z — permissions wlacu — resource-types co — services bt -o tsv)
my_lad_protected_settings=”{‘storageAccountName’: ‘$my_diagnostic_storage_account’, ‘storageAccountSasToken’: ‘$my_diagnostic_storage_account_sastoken’}”

# Finally, tell Azure to install and enable the extension.
az vm extension set — publisher Microsoft.Azure.Diagnostics — name LinuxDiagnostic — version 4.0 — resource-group $my_resource_group — vm-name $my_linux_vm — protected-settings “${my_lad_protected_settings}” — settings portal_public_settings.json

(from Azure Compute — Linux diagnostic extension 4.0 — Azure Virtual Machines | Microsoft Docs)

NetworkManager

We are going to be building a desktop system based on xRDP, so NetworkManager needs to work or most GNOME apps will not see the system as being online. This is a little more problematic than you might think, so getting NetworkManager working seems to be the most direct approach to fixing it. Normally, you would just edit /etc/netplan/50-cloud-init.yaml and add a renderer: NetworkManager line. This doesn’t work, because cloud-init regenerates the contents of the netplan file every boot.

There’s a lot of things that don’t work. I’ll list them all here to save you the trouble of bricking and rebuilding your machine:

Idea 1: Edit the cloud-init configuration files
Attempt 1: Make edits at the beginning
As per the cloud-init documentation, the customized pieces in /etc/cloud/cloud.cfg.d/*.cfg are processed in lexical order. So we can add our changes to /etc/cloud/cloud.cfg.d/10-custom.cfg. I copied the contents of /etc/netplan/50-cloud-init.yaml to 10-custom.cfg as this is the final configuration that I want. And setting it as early as possible should avoid problems, right?
Result: Brick. Apparently not.

Attempt 2: Make edits at the end
Well, if it didn’t work at the beginning, maybe we overwrote some critical configuration with our own?
Result: Brick. Maybe we’re still overwriting critical configuration too early.

Attempt 3: Disable network configuration component of cloud-init altogether and configure manually. (The instructions in the generated /etc/netplan/50-cloud-init.yaml will tell you how to do so).
Maybe we don’t need cloud-init to configure the network
Result: Brick. Yes, yes we do.

That seems to be pretty conclusive. We’re not going to simply inject the renderer: NetworkManager line into the cloud-init pipeline and not break cloud-init. And breaking cloud-init causes a brick.

Idea 2: rc.local
Attempt 1: Have nmcli connect to the device after initialization
rc.local is kind of hacky, but there’s really no good suggestion as to where to put arbitrary commands that don’t need a full-blown daemon script to run. We only need execute a single command once the network is initialized:

nmcli dev connect eth0

Adding this command to a new or existing file /etc/rc.local and rebooting will make eth0 a managed device. It doesn’t really matter how we got there.

eth0’s Shadow

I currently have a device, enP49906s1np0 that shadows eth0. When I reboot, it will have another name. I call it a shadow because it has the same MAC address but no IP address. When testing and starting NetworkManager manually, I found there were settings which would cause BOTH network interfaces to try and connect. However, only one of them can be active at a time, which causes a periodic error notification in GNOME when the shadow fails to connect.

colord

The “Authentication is Required to Create a Color Managed Device” dialog is well-covered in http://c-nergy.be/blog/?p=12073. TLDR, you will need to create a file /etc/polkit-1/localauthority/50-local.d/45-allow-colord.pkla:

[Allow Colord all Users]
Identity=unix-user:*
Action=org.freedesktop.color-manager.create-device;org.freedesktop.color-manager.create-profile;org.freedesktop.color-manager.delete-device;org.freedesktop.color-manager.delete-profile;org.freedesktop.color-manager.modify-device;org.freedesktop.color-manager.modify-profile
ResultAny=no
ResultInactive=no
ResultActive=yes

The next time you create a new RDP session, you should no longer be prompted for your credentials to create color managed devices.

PulseAudio xrdp modules

This is a matter of taste (I’m sure some of you think that sound is annoying). I prefer to have sound available through my RDP session though. It’s easy enough to install and easy enough to ignore. To install:

apt install build-essential

Enable all of the corresponding apt-src lines in /etc/apt/sources.list. You can do this through the GUI too in the Software & Updates application:

Once the Source code repositories are enabled (instructions taken from neutrinolabs/pulseaudio-module-xrdp: xrdp sink / source pulseaudio modules (github.com):

sudo apt update
cd $HOME
apt source pulseaudio
sudo apt build-dep pulseaudio
sudo apt install pulseaudio-dev
cd $HOME/pulseaudio-x.y.z
./configure
git clone https://github.com/neutrinolabs/pulseaudio-module-xrdp
cd pulseaudio-module-xrdp
./bootstrap
PULSE_DIR=$HOME/pulseaudio-x.y.z ./configure
make && sudo make install
pulseaudio -k

Ok, maybe my idea of easy isn’t the same as yours. But you only have to run these steps once.

I think the two biggest annoyances are the first two. I spent a lot of time rebuilding after bricking trying to get NetworkManager connected to eth0. I’m also annoyed that it’s more or less necessary. For example, Evolution insists that I’m offline unless the Internet is available through a NetworkManager-controlled device. The LinuxDiagnostic extension issue is more shocking to me than anything else. It shows a failed deployment using a pre-built Marketplace image. This is either a fault of the vendor, for not considering the Azure deployment process; or a fault of Microsoft, for not allowing the vendor the freedom to remove the ancient version of python that the extension requires. Either way, it’s time-consuming to fix and an error that shouldn’t be received.

Don’t get me wrong though, a Linux dev machine in Azure is a nice thing to have. It just adds a couple more hazards to the install process. Hopefully the above can help you through it.

--

--