Operating Systems Azure

openSUSE Leap 16.0 with GNOME Desktop on Azure User Guide

| Product: openSUSE Leap 16.0 with GNOME Desktop on Azure

Overview

This guide covers the deployment and configuration of openSUSE Leap 16.0 with the GNOME desktop on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.

openSUSE Leap is the openSUSE Project's community Linux distribution, sharing its core code base with SUSE Linux Enterprise 16. It is free to use, patch and redistribute, with no subscription and no licence key. This image is openSUSE Leap 16.0 with the distribution's own desktop added: the repo-oss pattern openSUSE calls GNOME Desktop Environment (Wayland). It is reached with any RDP client through GNOME Remote Desktop in system mode, so you meet the GNOME login screen and sign in to a full desktop session running on the virtual machine.

Remote access here is first party. The RDP server is GNOME Remote Desktop from openSUSE's own repo-oss repository, built and signed by SUSE, so nothing outside the distribution is added to reach the desktop.

The image is built so that a freshly deployed machine exposes nothing but SSH. Remote desktop ships switched off, no account has a password, and nothing listens on the RDP port until you decide to turn it on. A desktop login always needs a password, so the image never ships one: you set your own over SSH, then enable remote desktop with a single command.

What's included:

  • openSUSE Leap 16.0 on x86-64 with the 6.12 kernel-default kernel, with every available patch applied at build time
  • The GNOME desktop from repo-oss: GNOME Shell 48.4, the GDM 48 login screen and mutter 48.4, installed from the distribution's own gnome pattern without optional extras
  • Desktop applications: Files (Nautilus), Console, Text Editor, System Monitor, Settings and Passwords and Keys
  • GNOME Remote Desktop 48.3 in system mode, which gives RDP remote login through the GNOME login screen
  • A per-VM RDP credential and a per-VM self signed TLS certificate, generated at first boot and readable by root only
  • cloudimg-remote-desktop, a small helper to show the remote desktop state, switch it on and off, and print your VM's RDP credential
  • A daily unattended zypper patch timer that applies security and kernel patches and never reboots on its own
  • SELinux in enforcing mode, as openSUSE Leap 16 ships it
  • A Btrfs root file system on a 30 GiB operating system disk
  • Gen2 Hyper V virtual machine support
  • 24/7 cloudimg support

The desktop is a Wayland session. There is no Xorg server in this image; Xwayland 24.1 is present and runs X applications inside the Wayland session as normal.

Platform: Microsoft Azure (Gen2 Hyper V, x86-64) Default user: azureuser

The two secrets, and which one goes where

This is the single thing worth reading twice. On a machine with remote desktop turned on there are two separate secrets, and both are unique to your virtual machine:

  1. The per-VM RDP credential. Generated automatically at first boot into /root/cloudimg-remote-desktop-credentials.txt (mode 0600, root only). The username is your VM's own administrator account (the --admin-username you chose) and the password is 24 random alphanumeric characters. Your RDP client asks for this before the login screen is drawn, because GNOME Remote Desktop uses Network Level Authentication. It is not an operating system account and it cannot be used for SSH. Read it with sudo cloudimg-remote-desktop credentials.
  2. Your account password. You set this yourself with sudo passwd <your-admin-user>. This is what the GNOME login screen asks for once Network Level Authentication has passed. The image ships with no account password at all, which is why you have to choose one.

Also generated per VM at first boot: a self signed RSA-3072 TLS certificate for the RDP server, with the VM's hostname as its common name. Its SHA-256 fingerprint is written into the same credentials file, so you can compare it with whatever your RDP client shows you.

Nothing above is baked into the image, and no two machines you launch share any of it. The first boot unit writes the credential straight into GNOME Remote Desktop's own store without passing it on any logged command line, so it does not appear in the system journal.

Security posture

This image ships with no known credential:

  • No account has a password. The root account is locked and your administrator account is created at first boot with only the SSH key you supply.
  • SSH is key only (PasswordAuthentication no). Setting an account password for the desktop does not enable password logins over SSH.
  • The remote desktop server is installed but disabled: a new virtual machine listens on SSH port 22 only, and 22 is the only port the listing advertises.
  • At first boot the machine generates its own RDP credential and its own TLS certificate. Nothing is shared between two machines.
  • Remote desktop cannot be switched on until an administrator account has a password, so the login screen is never exposed with nothing behind it.
  • SSH host keys are removed before capture and regenerated on each machine at first boot, and /etc/machine-id is regenerated per machine, so no two machines share a host identity.
  • SELinux is left in enforcing mode, the openSUSE Leap 16 default, and GDM automatic login is not enabled.
  • There is no host firewall in this image. firewalld is not part of the openSUSE Leap 16 Azure base, so the Azure network security group is the packet filter. That is why the image keeps its listening surface to SSH alone, and why this guide recommends reaching the desktop through an SSH tunnel.
  • The Azure Entra ID login integration (himmelblau) that the openSUSE update stream offers is not installed. Unconfigured, it fails on every boot and generates a machine secret that would be shared between clones, so it is left out. Install and configure it yourself if you want Entra ID sign in.

Prerequisites

Before deploying this image, ensure you have:

  1. An active Microsoft Azure subscription
  2. Access to the Azure Portal or Azure CLI
  3. An SSH key pair for Linux VM access
  4. An RDP client: Windows App or Remote Desktop Connection on Windows, Windows App on macOS, or Remmina or FreeRDP on Linux

Recommended VM Size: Standard_B2ms (2 vCPU, 8 GB RAM) or larger for everyday desktop use. The login screen plus one remote session runs in about 1.5 GB of memory, so Standard_B2s (4 GB) works for light use, but applications you open need room of their own. There is no GPU requirement, as the desktop renders in software.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "openSUSE Leap 16.0 with GNOME Desktop cloudimg"
  2. Select the image and click Create
  3. Configure the basics:
  4. Subscription: Select your Azure subscription
  5. Resource Group: Create new or select existing
  6. Virtual Machine Name: Enter a name for your VM
  7. Region: Select your preferred Azure region
  8. Size: Standard_B2ms or larger
  9. Under Administrator Account, select SSH public key and enter your key
  10. Under Inbound Port Rules, allow SSH (port 22) only. You do not need to open port 3389: the recommended way to reach the desktop is through an SSH tunnel (Step 6)
  11. Click Review + Create, then Create

Option B: Azure CLI

Run this on your own workstation, substituting your resource group, VM name and preferred region. Accept the Marketplace terms once per subscription, then create the machine:

az vm image terms accept --urn cloudimg1647283583153:opensuse-leap-16-gui:default:latest

az vm create \
  --resource-group myResourceGroup \
  --name my-opensuse-desktop \
  --image cloudimg1647283583153:opensuse-leap-16-gui:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard

Step 2: Connect via SSH

Run these on your own workstation, not on the VM. Find the public IP, then connect:

az vm show --resource-group myResourceGroup --name my-opensuse-desktop --show-details --query publicIps -o tsv
ssh azureuser@<vm-ip>

There is no password to enter. If SSH asks you for one, the key you supplied at create time is not the key your client is offering.

Step 3: Confirm the release and the desktop

Check that the machine is openSUSE Leap 16.0, that it boots to the graphical target, that the GNOME login screen (GDM) is running, and which desktop packages are installed:

grep -E '^(PRETTY_NAME|VERSION_ID)=' /etc/os-release
uname -srm
systemctl get-default
systemctl is-active gdm.service
rpm -q --qf '%{NAME} %{VERSION}\n' gdm gnome-shell mutter gnome-remote-desktop

The terminal shows openSUSE Leap 16.0 in os-release, the 6.12 kernel-default kernel, the default target graphical.target, GDM reported active, and the installed versions of gdm, gnome-shell, mutter and gnome-remote-desktop

Expected output:

VERSION_ID="16.0"
PRETTY_NAME="openSUSE Leap 16.0"
Linux 6.12.0-160000.37-default x86_64
graphical.target
active
gdm 48.0+leap
gnome-shell 48.4
mutter 48.4
gnome-remote-desktop 48.3

The kernel release number moves forward as openSUSE publishes kernel updates, so yours may be newer.

The desktop comes from the distribution's own pattern, not from a third party repository:

zypper --non-interactive search --installed-only --type pattern gnome | grep -E '^i' || true
echo "packages installed: $(rpm -qa | wc -l)"
df -h /

There is no Xorg server in this image. The session is Wayland, and Xwayland runs X applications inside it:

rpm -q xorg-x11-server >/dev/null 2>&1 || echo "(no Xorg server: the desktop is a Wayland session)"
rpm -q --qf '%{NAME} %{VERSION}\n' xwayland

Step 4: Check that remote desktop is off

A new virtual machine has remote desktop switched off. The helper shows the whole picture in one command:

sudo cloudimg-remote-desktop status

The terminal shows cloudimg-remote-desktop status reporting the remote desktop service disabled and inactive, nothing listening on port 3389, the per-VM credential generated, this machine's TLS certificate fingerprint, and that no account can yet log in at the GNOME login screen

The helper lives at /usr/local/sbin/cloudimg-remote-desktop. On openSUSE Leap, sudo replaces your PATH with its own secure_path (/usr/sbin:/usr/bin:/sbin:/bin), which does not include /usr/local/sbin, so the image also ships /usr/sbin/cloudimg-remote-desktop as a symlink to it. The short form sudo cloudimg-remote-desktop status used throughout this guide therefore works, and so does the full path.

Expected output on a new VM (the fingerprint is unique to your machine):

remote desktop service: disabled / inactive
RDP backend: disabled
listening on 3389: no
per-VM RDP credential: generated (/root/cloudimg-remote-desktop-credentials.txt)
TLS certificate SHA-256: <the SHA-256 fingerprint of this VM's own certificate>
accounts able to log in at the GNOME login screen: none (set one with: sudo passwd <user>)

Confirm it from the network side as well:

sudo ss -tln | awk '$1=="LISTEN"{print $4}' | sort
0.0.0.0:22
[::]:22

SSH on port 22 is the only service listening on the network.

Step 5: Set your account password and turn remote desktop on

The GNOME login screen asks for your account password, and a new VM has none. Choose your own. Run this yourself on the VM and enter the new password twice when prompted:

sudo passwd azureuser

Your SSH access is unaffected: SSH remains key only, and this does not enable SSH password logins. Now switch remote desktop on:

sudo cloudimg-remote-desktop enable

Expected output:

remote desktop enabled: listening on port 3389
TLS certificate SHA-256: <the SHA-256 fingerprint of this VM's own certificate>
RDP credential: sudo cloudimg-remote-desktop credentials
safest route: ssh -L 3389:localhost:3389 <user>@<vm-ip>, then point your RDP client at localhost:3389
note: this image has no host firewall. The SSH tunnel needs no change at all;
      a DIRECT connection to 3389 needs an Azure NSG rule scoped to your own address.

If no administrator account has a password yet, the helper refuses rather than opening a login screen with nothing behind it, and tells you exactly which command to run first:

refusing to enable remote desktop: no administrator account has a password yet,
so the GNOME login screen would have nothing to accept. Set your own first:
  sudo passwd azureuser

The setting survives reboots. Under the hood the helper turns on the RDP backend of GNOME Remote Desktop's system configuration, runs systemctl enable --now gnome-remote-desktop.service, then waits until port 3389 is genuinely listening before it reports success.

Now print this VM's RDP credential, which you need in the next step:

sudo cloudimg-remote-desktop credentials
RDP_USERNAME=azureuser
RDP_PASSWORD=<24 random characters, generated at this VM's first boot>
RDP_PORT=3389
RDP_TLS_SHA256=<SHA-256 fingerprint of this VM's certificate>
RDP_TLS_SHA1=<SHA-1 fingerprint of the same certificate, shown as the thumbprint by Windows>

RDP_USERNAME is your own administrator account name, but RDP_PASSWORD is used by your RDP client only: it is not an operating system password and it does not work for SSH.

Step 6: Connect with your RDP client

Port 3389 is not open by default, and the SSH tunnel is the recommended route. It keeps RDP inside your existing SSH connection, so nothing new is exposed to the internet, and it needs no network security group change. On your own workstation, open the tunnel and leave it running:

ssh -N -L 3389:localhost:3389 azureuser@<vm-ip>

Then point your RDP client at localhost:3389:

  • Windows: Remote Desktop Connection (mstsc) or Windows App, computer localhost:3389
  • macOS: Windows App, add a PC with the name localhost:3389
  • Linux: Remmina (RDP), server localhost:3389, or FreeRDP 3 (xfreerdp on openSUSE and Fedora, xfreerdp3 on Debian and Ubuntu): xfreerdp /v:localhost:3389 /u:azureuser /gfx /bpp:32

When the client asks for credentials, enter RDP_USERNAME and RDP_PASSWORD from Step 5. This happens before any screen is drawn. On the first connection the client shows the server's certificate: it is self signed and unique to your VM, so compare its fingerprint with RDP_TLS_SHA256 (or RDP_TLS_SHA1, which is what Windows displays as the thumbprint) before you accept it.

The GNOME login screen then appears. Select your account and enter the password you set in Step 5, and the full desktop session opens.

If you prefer a direct connection instead of the tunnel, allow 3389 in the network security group from your own public address only, never from the whole internet. This image has no host firewall, so the network security group rule is the only change needed:

az network nsg rule create --resource-group myResourceGroup --nsg-name my-opensuse-desktopNSG \
  --name allow-rdp-from-me --priority 1010 --access Allow --protocol Tcp \
  --direction Inbound --destination-port-ranges 3389 --source-address-prefixes <your-public-ip>/32

Step 7: Use the desktop

The GNOME login screen of the openSUSE Leap 16.0 virtual machine displayed in an RDP session over the SSH tunnel, showing the date and clock in the top bar, the administrator account tile with a Not listed option beneath it, and the Leap logo

The openSUSE Leap GNOME desktop in the remote session after signing in, showing the default wallpaper, the GNOME top bar with the clock, and the screen sharing indicator confirming the session is remote

Open Activities, or press the Super key, to reach the application grid. Files sits in the dock, and the grid holds Text Editor, Settings and Console plus the YaST2, Utilities and System folders, which carry the remaining tools such as System Monitor, Passwords and Keys and YaST Software. These come from the gnome pattern and the few desktop tools this image adds; the image deliberately installs the pattern without its optional extras, so there is no web browser, office suite or media player until you add one.

A terminal inside the session behaves exactly as your SSH session does, and your administrator account keeps its sudo rights. To confirm you are on a Wayland session, run this in Console inside the desktop:

echo "$XDG_SESSION_TYPE"

To add software, use zypper as on any openSUSE Leap machine, for example sudo zypper install gnome-calculator libreoffice-writer, then open the application from the grid.

The GNOME application grid in the remote session, showing Text Editor, Settings and Console with the YaST2, Utilities and System folders, and Files in the dock along the bottom

The Console terminal open inside the remote GNOME desktop, showing the openSUSE Leap 16.0 release and the default target graphical.target

Disconnecting your RDP client leaves the session running on the VM; connect again and you return to it.

Step 8: Turn remote desktop off again

When you have finished, switch it back off. This closes port 3389 and keeps it closed across reboots:

sudo cloudimg-remote-desktop disable
remote desktop disabled: nothing listening on port 3389

sudo cloudimg-remote-desktop status shows the state at any time, whether the service is on or off.

Step 9: Verify the security posture

Confirm SELinux is enforcing, that SSH is key only, and that no account has a password until you set one:

getenforce
sudo sshd -T | grep -E '^(passwordauthentication|kbdinteractiveauthentication) '
sudo passwd -S root | awk '{print $1, $2}'
sudo awk -F: '$2 !~ /^[!*]/ && $2 != "" {n++} END {print "accounts with a password: " n+0}' /etc/shadow

Expected output on a new VM (after Step 5 the last line reads 1, your own account):

Enforcing
passwordauthentication no
kbdinteractiveauthentication no
root L
accounts with a password: 0

L in the second field means the root account is locked. The SSH policy is pinned by a drop in file that sorts ahead of every other one, so a later package update to the vendor configuration cannot quietly loosen it:

grep -vE '^#' /etc/ssh/sshd_config.d/00-cloudimg-hardening.conf
PermitRootLogin prohibit-password
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitEmptyPasswords no

The terminal shows SELinux reported Enforcing, the effective sshd policy with password authentication off, the root account locked, zero accounts carrying a password, no host firewall installed, and the remote desktop service switched off

Step 10: Patching and updates

Every available patch was applied when this image was built, and a daily timer keeps applying them on your machine:

systemctl is-enabled cloudimg-zypper-patch.timer
systemctl cat cloudimg-zypper-patch.service | grep '^ExecStart='

Expected output:

enabled
ExecStart=/usr/bin/zypper --non-interactive --gpg-auto-import-keys refresh
ExecStart=/usr/bin/zypper --non-interactive patch --with-interactive --auto-agree-with-licenses --auto-agree-with-product-licenses --replacefiles

--with-interactive matters. zypper marks every patch that suggests a reboot, which includes every kernel and systemd security fix, as interactive, and a plain non-interactive zypper patch silently skips those. With the flag the timer applies them too. It never restarts the machine itself, so check whether a restart is owed and pick your own window:

sudo zypper patch-check >/dev/null 2>&1; echo "exit=$? (0 = nothing pending, 100 = patches available, 101 = security patches available)"
sudo zypper needs-rebooting >/dev/null 2>&1; echo "needs-rebooting exit=$? (0 = no reboot needed, 102 = reboot needed)"

You can always patch on your own schedule with sudo zypper patch --with-interactive, and reboot if a new kernel was installed. To opt out of the automatic run, use sudo systemctl disable --now cloudimg-zypper-patch.timer.

Step 11: Networking and the firewall

The Azure network security group is the only packet filter for this image; there is no host firewall installed:

rpm -q firewalld >/dev/null 2>&1 || echo "(no host firewall installed: the Azure network security group is the packet filter)"
nmcli -t -f DEVICE,TYPE,STATE device status | grep '^eth0'
for u in rpcbind.socket gnome-remote-desktop.service; do echo "$u: $(systemctl is-enabled "$u" 2>/dev/null || true)"; done
(no host firewall installed: the Azure network security group is the packet filter)
eth0:ethernet:connected
rpcbind.socket: disabled
gnome-remote-desktop.service: disabled

The network stack is NetworkManager, the native openSUSE Leap 16 stack, configured by the Azure agent and cloud-init exactly as on the server image; the desktop adds no second network stack. The rpcbind portmapper is installed but left disabled, never masked, so NFSv3 is one command away with sudo systemctl enable --now rpcbind.socket. If you want a host firewall as well, sudo zypper install firewalld adds one: allow SSH in it before you enable it.

Step 12: The disk layout

The root file system is Btrfs on the operating system disk, laid out as openSUSE Leap 16's Azure image lays it out, with separate subvolumes for /home, /var, /opt, /root, /srv and /usr/local:

findmnt -no SOURCE,FSTYPE /
df -h /

Verify what you are running

Three commands answer the three questions that matter: which release this is, that it is a desktop image, and whether remote desktop is currently on.

grep '^PRETTY_NAME=' /etc/os-release
systemctl get-default
sudo cloudimg-remote-desktop status

Common Use Cases

  • A cloud workstation for openSUSE and SUSE Linux Enterprise development with a full GNOME desktop, reachable from any RDP client
  • Running graphical administration and data tools close to your Azure resources
  • Testing applications against the SUSE Linux Enterprise 16 code base on a free community distribution
  • Training labs and demonstrations that need a desktop rather than a shell
  • A secure jump desktop, reachable only through an SSH tunnel

Troubleshooting

The RDP client connects, then the screen stays black or it disconnects

GNOME Remote Desktop requires the RDP graphics pipeline. Current clients support it: Windows App, Remote Desktop Connection (mstsc), Windows App on macOS and Remmina are all fine. With FreeRDP you must pass /gfx /bpp:32; without those flags the server closes the connection after authentication. Read the server side with:

sudo journalctl -u gnome-remote-desktop --no-pager -n 20

The login screen never appears

The desktop needs the Hyper-V DRM display driver, hyperv_drm, which provides the display device GNOME Shell draws on. openSUSE's kernel-default builds no competing framebuffer driver, so it always binds; confirm it with:

ls /dev/dri
lsmod | awk '$1=="hyperv_drm"{print $1}'

If /dev/dri is empty, you are probably running a kernel other than kernel-default. Reinstall it with sudo zypper install -f kernel-default and reboot.

"Connection refused" on localhost:3389

Remote desktop is disabled on a fresh VM by design. Run sudo cloudimg-remote-desktop enable first, and check the SSH tunnel is still up in its own terminal window. sudo cloudimg-remote-desktop status tells you whether anything is listening on 3389.

The login screen appears but rejects my password

That screen wants your account password, the one you set with sudo passwd <your-user>, not the RDP credential. The RDP credential was already used, before the screen was drawn. If you have not set an account password yet, set it over SSH and try again.

My RDP client says the credentials are wrong before any screen appears

That is the opposite case: the client wants the RDP credential from sudo cloudimg-remote-desktop credentials, not your account password.

A certificate warning on the first connection

Expected. The TLS certificate is self signed and unique to your virtual machine, generated at its first boot with the VM's hostname as its common name. Verify the SHA-256 fingerprint your client shows against RDP_TLS_SHA256 from sudo cloudimg-remote-desktop credentials (Windows shows the SHA-1 value as the thumbprint), then accept it.

Configuring GNOME Remote Desktop by hand

grdctl --system ... works from your own SSH login shell. It re-runs itself through pkexec as the gnome-remote-desktop account, and SELinux refuses that step from a system service context, where it fails without changing anything. In scripts and systemd units, run it as that account directly instead: sudo runuser -u gnome-remote-desktop -- env HOME=/var/lib/gnome-remote-desktop grdctl status.

Cannot connect via SSH

  1. Verify the VM is in Running state in the Azure Portal
  2. Check that port 22 is allowed in the Network Security Group
  3. Ensure you are using the administrator username you named at create time
  4. Verify your SSH key matches the one you supplied at create time. Password login over SSH is disabled by design, so a password prompt means key negotiation already failed.

A service is blocked and the logs mention SELinux

SELinux is enforcing, which is the secure default and should stay that way. On this image denials are recorded by the audit daemon, not the journal, so read them with ausearch:

sudo ausearch -m AVC -ts recent </dev/null 2>/dev/null || echo "no recent AVC denials"

Most denials on a fresh machine come from software installed into a non standard path. Relabel with sudo restorecon -Rv /path before considering any policy change.

Important Notes

openSUSE Leap is free and open source, and there is no subscription, licence key or support contract required to use, patch or redistribute it. The distribution is not covered by a single licence: it is a collection of thousands of independently packaged components, each carrying its own terms, predominantly GPL and LGPL, with MIT, BSD, Apache 2.0, MPL and others. The GNOME desktop, GDM and GNOME Remote Desktop are free software packaged in openSUSE's repo-oss repository. Every package's terms are readable on the machine with rpm -qi <package> and under /usr/share/licenses/.

openSUSE Leap 16.0 is not an end of life product. It was released in October 2025, and the openSUSE Project supports each Leap 16 minor release for 24 months, with a new minor release each year. Check the openSUSE lifecycle page for the dates that apply to your deployment.

openSUSE is a trademark of SUSE LLC, and GNOME is a trademark of the GNOME Foundation. Both names are used here nominatively, only to identify the distribution and the desktop environment this image contains. cloudimg is not affiliated with, endorsed by or sponsored by SUSE, the openSUSE Project or the GNOME Foundation.

Support

For assistance with this image, contact cloudimg support: