Operating Systems Azure

Debian 13 with XFCE Desktop on Azure User Guide

| Product: Debian 13 with XFCE Desktop on Azure

Overview

This guide covers the deployment and configuration of Debian 13 "trixie" with the XFCE desktop on Microsoft Azure using cloudimg's pre configured virtual machine image from the Azure Marketplace.

Debian is one of the oldest and most widely used Linux distributions, produced by the Debian Project. Debian 13 "trixie" was released on 9 August 2025 and has security support from the Debian Security Team followed by Debian LTS, to 30 June 2030. This image is the cloudimg Debian 13 base with Debian's own XFCE 4.20 desktop added (the task-xfce-desktop selection Debian's installer uses) and xrdp 0.10 set up as the remote desktop server: you connect with any RDP client, sign in with your own account name and password, and get a full XFCE session running on the virtual machine.

Everything the image adds comes from Debian's own main archive, the same archive and the same security update stream as the rest of the operating system.

XFCE is deliberately light. The desktop idles in roughly 500 to 650 MB of memory on this build, which is why the image is comfortable on a 2 vCPU, 4 GB Standard_B2s.

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.

What's included:

  • Debian 13 "trixie" with the XFCE 4.20 desktop (Thunar file manager, XFCE Terminal, Mousepad text editor, Task Manager, Application Finder, Settings Manager) and the LightDM display manager
  • xrdp 0.10.1 with xorgxrdp, configured for remote desktop sessions over TLS. The session manager talks to the server over a local UNIX socket, so it adds no network port of its own
  • xrdp at 0.10.1-3.1+deb13u2 or later, the Debian security release that fixes CVE-2025-68670 and the later 2026 xrdp advisories
  • A per-VM TLS certificate and a per-VM xrdp RSA key, 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 connection details
  • Every available security update applied at build time, with unattended-upgrades armed so the machine keeps patching itself
  • LLMNR switched off in systemd-resolved, so the machine does not listen on port 5355 as a stock Debian 13 machine does
  • The Azure provisioning path unchanged: cloud-init, the Azure Linux Agent and systemd-networkd, on Debian's cloud kernel
  • Gen2 Hyper V virtual machine support
  • 24/7 cloudimg support

What's deliberately NOT included: a web browser (install one with sudo apt install firefox-esr), an office suite (sudo apt install libreoffice), NetworkManager (networking is managed by systemd-networkd, the Azure default), printing, Bluetooth, the Avahi service discovery daemon, the GVFS network file system backends, and any screen locker. None of these add anything on a cloud server by default, and several would open network listeners. The Applications menu's "Web Browser" and "Mail Reader" entries are XFCE's generic handlers: they will not do anything until you install a browser or a mail client.

Platform: Microsoft Azure (Gen2 Hyper V, x64) Default user: azureuser

Security posture

This image ships with no known credential:

  • No account has a password. The root account is locked, and azureuser 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.
  • At first boot the machine generates its own TLS certificate and key for xrdp, and its own xrdp RSA key. Nothing is shared between two machines, and nothing is baked into the image.
  • Remote desktop cannot be switched on until an administrator account has a password, so an RDP login box is never exposed with nothing to protect it.
  • xrdp-sesman is configured to refuse root logins, and every session module except the local Xorg one has been removed from xrdp.ini, so the RDP login box cannot be used to make your VM open outbound connections elsewhere.
  • The machine identity and the SSH host keys are regenerated uniquely on every instance, and AppArmor is enabled.

There is only one password, and it is yours. Unlike RDP servers that carry a credential of their own, xrdp authenticates you through PAM against your ordinary Linux account. The password the RDP login box asks for is the one you set with sudo passwd, and until you set it nobody can sign in at all.

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_B2s (2 vCPU, 4 GB RAM) or larger. For heavier desktop work pick Standard_D2s_v5 or larger. There is no GPU requirement: the desktop renders in software.

Step 1: Deploy the Virtual Machine

Option A: Azure Portal

  1. Navigate to the Azure Marketplace and search for "Debian 13 with XFCE 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_B2s 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

cloudimg images carry a Marketplace purchase plan, so accept its terms once per subscription, then create the VM:

az vm image terms accept --urn cloudimg1647283583153:debian-13-gui-xfce:default:latest

az vm create \
  --resource-group myResourceGroup \
  --name my-debian-xfce \
  --image cloudimg1647283583153:debian-13-gui-xfce:default:latest \
  --size Standard_B2s \
  --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-debian-xfce --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 the release and point release, that the machine booted to the graphical target, that the LightDM display manager is running, and which desktop packages are installed:

grep -E '^(PRETTY_NAME|VERSION_ID)=' /etc/os-release
cat /etc/debian_version
systemctl get-default
systemctl is-active lightdm
dpkg-query -W -f='${Package} ${Version}\n' task-xfce-desktop xfce4 xfce4-session lightdm xrdp xorgxrdp

Expected output (the point release and package revisions move forward as Debian publishes updates):

PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
VERSION_ID="13"
13.7
graphical.target
active
lightdm 1.32.0-6+b2
task-xfce-desktop 3.81
xfce4 4.20.1
xfce4-session 4.20.2-2
xorgxrdp 1:0.10.2-1
xrdp 0.10.1-3.1+deb13u2

The terminal shows os-release reporting Debian GNU/Linux 13 trixie at point release 13.7, the default target graphical.target, LightDM active, and the installed versions of task-xfce-desktop, xfce4, xfce4-session, lightdm, xrdp and xorgxrdp

Step 4: Check that remote desktop is off

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

sudo cloudimg-remote-desktop status
sudo ss -tln | awk '$1=="LISTEN"{print $4}' | sort

Expected output (the certificate fingerprint is unique to your VM):

remote desktop service: disabled / inactive
session manager: disabled / inactive
listening on 3389: no
per-VM TLS certificate: generated (/etc/xrdp/cert.pem)
TLS certificate SHA-256: D2:32:3D:93:E7:20:C9:7E:5E:7A:0F:48:4D:CA:C1:85:88:10:FA:CA:9E:C9:89:BD:F1:11:64:04:91:CC:FF:D9
accounts able to log in at the XFCE remote desktop: none (set one with: sudo passwd <user>)
0.0.0.0:22
127.0.0.53%lo:53
127.0.0.54:53
[::]:22

The terminal shows cloudimg-remote-desktop status reporting the xrdp service and session manager disabled and inactive, nothing listening on 3389, a per-VM TLS certificate generated, and the TCP listeners limited to SSH on port 22 and the loopback resolver

The only listener reachable from outside the machine is SSH on port 22. The two port 53 entries are the local DNS resolver, bound to loopback addresses only.

Step 5: Set your password and turn remote desktop on

The XFCE login box 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. Now switch remote desktop on:

sudo cloudimg-remote-desktop enable

Expected output:

remote desktop enabled: listening on port 3389
TLS certificate SHA-256: D2:32:3D:93:E7:20:C9:7E:5E:7A:0F:48:4D:CA:C1:85:88:10:FA:CA:9E:C9:89:BD:F1:11:64:04:91:CC:FF:D9
sign in with your own account name and the password you set with sudo passwd
safest route: ssh -L 3389:localhost:3389 <user>@<vm-ip>, then point your RDP client at localhost:3389

If no administrator account has a password yet, the helper refuses and tells you which command to run first. The setting survives reboots. Under the hood it runs systemctl enable --now xrdp.service, which starts the session manager with it.

Print this VM's connection details:

sudo cloudimg-remote-desktop credentials

The output lists RDP_USERNAME (your admin account name), RDP_PORT and the TLS certificate fingerprints. Note what it says about the password: there isn't a separate one. RDP_PASSWORD_SOURCE records that the password is your own account password.

Step 6: Connect with your RDP client

The recommended route keeps port 3389 closed to the internet and carries RDP inside your SSH connection. On your workstation, open a 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: xfreerdp3 /v:localhost:3389 /u:azureuser /gfx /bpp:32

On 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 xrdp login box appears. The Session list has one entry, Xorg, which is the one you want:

The xrdp login box shown in an RDP session, with the session type set to Xorg and fields for username and password

Enter your account name and the password you set in Step 5. The XFCE desktop appears:

The XFCE desktop in a remote session on Debian 13, with the Applications menu and clock in the top panel, the Home and File System icons on the desktop, and the application dock along the bottom

Disconnecting your RDP client leaves the session running on the VM; connect again with the same account and you return to it. xrdp asks for your password again every time you connect, so a disconnected session is not left unprotected.

If you prefer a direct connection instead of the tunnel, allow port 3389 in the VM's network security group from your own public address only, never from the whole internet. For example, from your workstation (replace the placeholders):

az network nsg rule create --resource-group myResourceGroup --nsg-name my-debian-xfceNSG \
  --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

Open the Applications menu at the top left to see what is installed:

The XFCE Applications menu open in the remote session on Debian 13, listing the installed accessories, system tools and settings

A terminal is in the dock at the bottom, and in Applications under Terminal Emulator. azureuser keeps its Azure administrator rights, so sudo works in the desktop exactly as it does over SSH:

XFCE Terminal inside the remote desktop session showing Debian GNU/Linux 13 trixie, the graphical target, and cloudimg-remote-desktop status reporting the service enabled and listening on port 3389

To add software, use apt in the terminal as on any Debian machine, for example sudo apt install libreoffice or sudo apt install firefox-esr.

Settings live in Applications, then Settings, then Settings Manager: appearance, display, keyboard layout and the panel are all configured there. The display resolution of a remote session is set by your RDP client, not by the VM.

Step 8: Verify the security posture

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

sudo sshd -T | grep -E '^(permitrootlogin|passwordauthentication) '
sudo passwd -S root
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):

permitrootlogin without-password
passwordauthentication no
root L 2009-12-22 -1 -1 -1 -1
accounts with a password: 0

The terminal shows the effective sshd policy with permitrootlogin without-password and passwordauthentication no, the root account locked, zero accounts with a password, eth0 routable and configured under systemd-networkd, and LLMNR switched off

without-password is how this OpenSSH release prints prohibit-password: root may not authenticate with a password. L means the root account is locked.

Step 9: Networking

The Azure network interface is configured by cloud-init and systemd-networkd, exactly as on Debian's own cloud image. The XFCE package set does not install NetworkManager, so no second network stack competes for your interface:

networkctl list --no-legend | awk '$2=="eth0"'

Expected output:

  2 eth0 ether    routable configured

Because NetworkManager is not installed, there is no network panel in the XFCE settings; that is expected. If you want one, install NetworkManager yourself and test the change from the Azure serial console before you reboot.

Stock Debian 13 enables LLMNR in systemd-resolved, which listens on port 5355 on every interface. This image switches it off with a small drop-in file. Check it:

grep -vE '^[[:space:]]*(#|$)' /etc/systemd/resolved.conf.d/20-cloudimg-no-llmnr.conf
resolvectl llmnr

Expected output:

[Resolve]
LLMNR=no
MulticastDNS=no
Global: no
Link 2 (eth0): no

To turn LLMNR back on, delete that file and run sudo systemctl restart systemd-resolved.

The Azure Network Security Group is the enforced firewall. No host firewall is installed; if you add one, allow SSH first, and allow 3389 only if you connect directly rather than through the tunnel.

Step 10: Turn remote desktop off, or change your password

To switch remote desktop off again (the setting survives reboots), run this yourself:

sudo cloudimg-remote-desktop disable

To change the password the RDP login box asks for, change your account password; they are the same thing:

sudo passwd azureuser

To replace this VM's TLS certificate with one of your own, write it to /etc/xrdp/cert.pem and /etc/xrdp/key.pem (the key readable by group xrdp) and restart the service with sudo systemctl restart xrdp.

Step 11: Check the patch level

The image is fully updated at build time. Refresh the package lists and confirm no upgrades are pending (grep -c exits non-zero on a zero count, hence the || true):

sudo apt-get update -qq
echo "pending upgrades: $(apt-get -s dist-upgrade | grep -c '^Inst ' || true)"

Expected output on a freshly built image:

pending upgrades: 0

unattended-upgrades installs Debian security updates automatically. You can still update on your own schedule with sudo apt-get update && sudo apt-get -y dist-upgrade, and reboot if a new kernel was installed. Debian publishes point releases every couple of months, so after a while this count will naturally be above zero until you upgrade.

Common Use Cases

  • A lightweight cloud workstation for Linux development, reachable from any RDP client
  • Running graphical administration and data tools close to your Azure resources without paying for a large VM
  • 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 but the screen is black, or the session closes immediately

Check what the session manager recorded, on the VM:

sudo tail -n 30 /var/log/xrdp-sesman.log

A healthy sign-in logs Access permitted for user: <your account>, then Starting X server on display 10 and Session in progress on display :10. If instead you see pam_authenticate failed: Authentication failure followed by AUTHFAIL: user=<your account>, the password is wrong or the account has none yet, so set it with sudo passwd <user> over SSH and try again.

I connected a second time and was immediately disconnected

You get one XFCE desktop session per account. If you disconnect and reconnect later, xrdp returns you to the session you left, which is the normal path and it works. But if you open a second connection while the first is still attached, xrdp starts a second session for the same account, xfce4-session refuses to run twice for one user and exits, and the new connection is dropped. This is how XFCE behaves anywhere, not something specific to this image.

If you need two desktops at once, sign in as two different accounts: create the second one with sudo adduser <name> and give it a password. To abandon a session you can no longer reach, end it from SSH with sudo pkill -u <your-account> xfce4-session, then connect again.

The RDP login box will not accept my password

The account has no password yet, or you typed a different account's name. Set it again with sudo passwd azureuser over SSH, then retry. The username is your Linux account name, not an email address.

I get "connection refused" on localhost:3389

The tunnel is not up, or remote desktop is still off. Check sudo cloudimg-remote-desktop status on the VM, and confirm your ssh -N -L 3389:localhost:3389 command is still running on your workstation.

The desktop resolution is wrong

Resize is controlled by your RDP client. In Remote Desktop Connection set the display size before connecting; with FreeRDP pass /size:1920x1080 or /f for full screen.

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 correct username: azureuser
  4. Verify your SSH key matches the one you supplied at create time. Password login over SSH is disabled by design.

Azure agent not running

systemctl is-active walinuxagent

If it does not print active, start it yourself with sudo systemctl enable --now walinuxagent.

Important Notes

  • One password, and it is yours. xrdp signs you in with your own Linux account password. The image ships none; you set it with sudo passwd.
  • Remote desktop ships off. A new machine listens on SSH only. The listing does not pre-open 3389 in your network security group.
  • Use an SSH tunnel rather than exposing 3389 to the internet.
  • Everything is from Debian main. The desktop, LightDM and xrdp are Debian packages from the same archive and the same security update stream as the rest of the operating system.
  • Debian 13 "trixie" has security support to 30 June 2030.
  • Debian is free and open source. It is not covered by a single licence: it is a distribution assembled from thousands of independently licensed packages, each carrying its own terms, including the GPL, LGPL, MIT, BSD, Apache 2.0 and MPL. XFCE is free software under the GPL and LGPL; xrdp and xorgxrdp are under the Apache Licence 2.0. Every package's terms are readable with dpkg -s <package> and under /usr/share/doc/<package>/copyright. No subscription or licence key is required to run this image.
  • cloudimg is not affiliated with, endorsed by or sponsored by the Debian Project or the Xfce project. "Debian" is a trademark of Software in the Public Interest, Inc.; the names are used here nominatively, only to identify the software this image contains.

Support

For assistance with this image, contact cloudimg support: