Deployment guide

Debian 13 Gui

Overview

This guide shows how to deploy and configure Debian 13 "trixie" with the GNOME desktop on Microsoft Azure, using SecureAnyCloud's preconfigured 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. It has security support from the Debian Security Team, followed by Debian LTS, to 30 June 2030.

This image is the SecureAnyCloud Debian 13 base with Debian's own GNOME 48 desktop added from Debian main (GDM, GNOME Shell, GNOME Session, Nautilus and the standard GNOME applications). It also includes GNOME's own remote desktop server, gnome-remote-desktop, set up for remote login. You connect with any RDP client, see the GNOME login screen, and sign in to a full desktop session running on the virtual machine.

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 turn it on. A desktop login always needs a password, so the image never ships one. You set your own over SSH, and then enable remote desktop with a single command.

What you get:

  • Debian 13 "trixie" with the GNOME 48 desktop (GDM login screen, GNOME Shell, Files, Terminal, Text Editor, System Monitor, Settings) from Debian main. GVFS is rebuilt from Debian source without the Google Drive backend, so every remote-location type except Google Drive (google-drive://) is available in Files
  • GNOME Remote Desktop 48.1 in system mode: RDP remote login through the GNOME login screen, with the modern RDP graphics pipeline
  • A per-VM RDP credential and a per-VM self-signed TLS certificate, both generated at first boot and readable by root only
  • sac-remote-desktop, a small helper to show the remote desktop state, switch it on and off, and print your VM's RDP credential
  • Every available security update applied at build time, with unattended-upgrades armed so the machine keeps patching itself
  • The Azure provisioning path unchanged: cloud-init, the Azure Linux Agent and systemd-networkd
  • Gen2 Hyper-V virtual machine support
  • 24/7 SecureAnyCloud support

A deliberate difference from Debian's stock cloud image: this image runs Debian's generic linux-image-amd64 kernel rather than the linux-image-cloud-amd64 flavour that Debian's own cloud images boot. The cloud flavour is stripped for headless servers and omits the DRM graphics drivers, including hyperv_drm. Without that driver there is no /dev/dri device, GNOME cannot start a graphical session, and the login screen never appears.

The generic flavour is a fully supported Debian kernel on exactly the same security update stream, and it simply carries more drivers. If you rebuild or re-pin the kernel yourself, keep the generic flavour or the desktop stops working.

What is deliberately not included: a web browser, NetworkManager (networking is managed by systemd-networkd, the Azure default), printing, Bluetooth, the Avahi service discovery daemon and the GNOME first-login wizard. None of these add anything on a cloud server, and several would open network listeners. Install anything you need with sudo apt install.

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.
  • The RDP credential and the RDP TLS certificate are generated on your virtual machine at first boot. They are unique to that machine and are not baked into the image, so no two deployments share them.
  • LLMNR is switched off. Debian 13's systemd-resolved enables LLMNR by default, which listens off-box on TCP and UDP port 5355. This image disables it, so the only off-box listener is SSH.

Prerequisites

  • An active Microsoft Azure subscription
  • Azure CLI installed and authenticated, or access to the Azure Portal
  • An SSH key pair
  • An RDP client. Windows App (Windows, macOS, iOS, Android), the built-in Windows Remote Desktop Connection (mstsc), and Remmina and FreeRDP 3 on Linux all work.
  • A virtual machine size with at least 8 GB of RAM. Standard_B2ms is the recommended size and is what this image is tested on. GNOME plus a remote session does not fit comfortably in the 4 GB of a Standard_B2s.
1

Deploy the virtual machine

Option A: Azure Portal

  • Sign in to the Azure Portal.
  • Search the Marketplace for Debian 13 with GNOME Desktop and select the SecureAnyCloud offer.
  • Choose Create.
  • Select your subscription, resource group and region.
  • Enter a name for the virtual machine.
  • Choose a size of Standard_B2ms or larger.
  • Set the authentication type to SSH public key, with username azureuser and your own public key.
  • Under Inbound port rules, allow SSH (22) only. Do not open 3389. The recommended route to the desktop is an SSH tunnel, and remote desktop is switched off on a new machine anyway.
  • Select Review + create, and then Create.

Option B: Azure CLI

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

az vm image terms accept --urn sac1647283583153:debian-13-gui:default:latest
az vm create \
  --resource-group myResourceGroup \
  --name my-debian-13-gui-vm \
  --image sac1647283583153:debian-13-gui:default:latest \
  --size Standard_B2ms \
  --admin-username azureuser \
  --generate-ssh-keys \
  --public-ip-sku Standard
2

Connect via SSH

ssh azureuser@<your-vm-public-ip>

You do everything in this guide over SSH. You do not need the Azure serial console.

3

Confirm the release and the desktop

cat /etc/os-release
cat /etc/debian_version uname -r

The output shows Debian GNU/Linux 13 (trixie), a point release of 13.x, and a kernel ending -amd64 (the generic flavour, not -cloud-amd64).

Confirm that the desktop is installed and the machine boots to a graphical login screen:

systemctl get-default
systemctl is-active graphical.target
systemctl is-active gdm.service dpkg-query -W -f='${Package} ${Version}\n' gdm3 gnome-shell gnome-session gnome-remote-desktop nautilus

systemctl get-default should print graphical.target, both is-active checks should print active, and dpkg-query should list GDM, GNOME Shell, GNOME Session, GNOME Remote Desktop and Nautilus at version 48.x.

Check the graphics device that the desktop renders on:

ls -l /dev/dri/

The output shows card0. If that directory is missing, the machine is running the wrong kernel flavour. See Troubleshooting.

4

Check that remote desktop is off

sudo sac-remote-desktop status

On a new machine, the output reports the service as disabled / inactive, the RDP backend as disabled, nothing listening on 3389, a per-VM RDP credential that has been generated, and no accounts able to log in at the GNOME login screen.

Confirm that nothing but SSH is listening off-box:

ss -tln

The only non-loopback listener is port 22.

5

Set your password and turn remote desktop on

The GNOME login screen asks for your own account password. The image does not ship one, so set it now:

sudo passwd azureuser

This password is used only at the graphical login screen. SSH remains key-only.

Now turn remote desktop on:

sudo sac-remote-desktop enable

The helper refuses to enable remote desktop while no administrator account has a password, so a login screen is never exposed with nothing behind it. Once remote desktop is enabled, the helper reports that port 3389 is listening and prints the TLS certificate fingerprint.

Print this machine's RDP credential:

sudo sac-remote-desktop credentials

The output contains RDP_USERNAME, RDP_PASSWORD, RDP_PORT and the TLS fingerprints. There are two secrets, and they are different:

  • The RDP credential above is requested by your RDP client before anything is drawn (Network Level Authentication). It is not an operating system account and cannot be used for SSH.
  • The account password you set with sudo passwd is what the GNOME login screen asks for once the session opens.
6

Connect with your RDP client

The recommended route is an SSH tunnel, so port 3389 is never exposed to the internet. On your own workstation, run:

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

Leave that command running, and then point your RDP client at localhost:3389.

  • Your client warns about the self-signed certificate. Compare its fingerprint with the RDP_TLS_SHA256 value from Step 5, and then accept it.
  • At the first prompt, enter the RDP credential from Step 5.
  • When the GNOME login screen appears, select your user and enter the account password you set in Step 5.

If you prefer not to tunnel, add an Azure network security group rule that allows TCP 3389 from your own IP address only (/32). Do not open 3389 to the internet.

7

Use the desktop

You now have a full GNOME 48 session. The Activities overview (top left, or the Super key) gives you the application grid. Files, Terminal, Text Editor, System Monitor and Settings are installed.

The machine has no GPU acceleration, so expect software rendering. For everyday administration, editing and browsing of local files, this is usable at 1280x720 or 1920x1080.

Remote locations in Files

Files can open remote locations over SMB/CIFS (Windows and Samba shares), SFTP, WebDAV, NFS, AFP and FTP. It can also browse Android phones over MTP and iPhones/iPads over AFC, read cameras over PTP, open archives in place, and mount Microsoft OneDrive.

In Files, choose Network in the sidebar. Type an address such as smb://fileserver/share or sftp://host/ into the Server address box at the bottom, and then select Connect. Alternatively, use gio mount from a terminal:

# list the location types this image can mount ls /usr/share/gvfs/mounts/ | sed 's/\.mount$//'

Google Drive is the one exception: it is not available in Files on this image. You can still add a Google account under Settings -> Online Accounts and use it in Calendar and Contacts. The account's page offers only Mail, Calendar and Contacts, with no Files switch. Drive does not appear in the Files sidebar, and google-drive:// locations do not open. (The Connect an Account list still describes Google as "Email, calendar, contacts, files". That is a fixed label in Settings.) Microsoft 365 accounts are unaffected and still offer Files through the OneDrive backend.

This is deliberate. Google Drive support is the only part of GVFS that needs the libgdata library, so this image ships GVFS rebuilt from Debian's own source with that one backend switched off (the same configuration Debian ships on i386). In addition, /etc/goa.conf tells GNOME Online Accounts not to offer Files for Google accounts.

To get Google Drive in Files, switch back to Debian's stock GVFS build, which pulls libgdata back in. Then remove the [google] section from /etc/goa.conf, and sign out and back in. The SecureAnyCloud build carries a higher version number than the archive copy, so a plain apt-get install is a no-op and you must downgrade explicitly:

V="$(apt-cache madison gvfs-backends | awk -F'|' 'NR==1{gsub(/ /,"",$2); print $2}')"
sudo apt-get install --allow-downgrades gvfs=$V gvfs-backends=$V gvfs-common=$V gvfs-daemons=$V gvfs-fuse=$V gvfs-libs=$V
sudo sed -i '/^\[google\]/,/^files=/d' /etc/goa.conf

Debian security updates to GVFS are not blocked. The SecureAnyCloud build is versioned just below Debian's next GVFS update, so when Debian publishes one, the machine moves onto Debian's build. That build brings the Google Drive backend and libgdata back with it.

8

Verify the security posture

Confirm that no account carries a password hash other than the one you just set:

sudo awk -F: '($2 ~ /^\$/) {print $1}' /etc/shadow

Only azureuser appears, because you set that password yourself in Step 5.

Confirm that SSH is still key-only:

sudo sshd -T | grep -E '^(passwordauthentication|permitrootlogin)'

Confirm that the RDP TLS certificate belongs to this machine:

sudo openssl x509 -in /var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/rdp-tls.crt -noout -subject -fingerprint -sha256

The CN is your VM's hostname, not a SecureAnyCloud build machine.

9

Networking

Networking is handled by cloud-init and systemd-networkd, the Azure default. NetworkManager is not installed.

networkctl status resolvectl status

/etc/systemd/resolved.conf.d/20-sac-no-llmnr.conf disables LLMNR. To re-enable it, delete that file and run sudo systemctl restart systemd-resolved.

10

Turn remote desktop off, or change the RDP credential

To switch remote desktop off again and close the port:

sudo sac-remote-desktop disable

To rotate the RDP credential to a new random password:

sudo grdctl --system rdp set-credentials "$(whoami)" "$(openssl rand -base64 48 | tr -dc 'A-Za-z0-9' | cut -c1-24)" sudo systemctl restart gnome-remote-desktop.service
sudo sac-remote-desktop credentials
11

Check the patch level

sudo apt-get update echo "pending upgrades: $(apt-get -s dist-upgrade | grep -c '^Inst ' || true)" systemctl is-enabled unattended-upgrades.service

The image is patched at build time and ships with unattended-upgrades armed, so the machine keeps applying security updates on its own.

Common use cases

  • A Linux desktop in Azure for developers who need a graphical toolchain, an IDE or a browser close to other Azure resources
  • A jump box with a real desktop for administering systems that only expose web or graphical consoles inside a virtual network
  • Training, demonstration and lab environments where every student needs an identical Debian desktop
  • Testing desktop Linux software against Debian 13 without local hardware

Troubleshooting

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

Check that the handover service is running in your session:

systemctl --user status sac-remote-desktop-handover.service journalctl -b | grep -i handover

GNOME's remote login needs a "handover" helper in both the login screen and your session. This image ships that wiring. If you removed /usr/local/libexec/sac-grd-remote-session, /etc/systemd/user/sac-remote-desktop-handover.service or /usr/share/gdm/greeter/autostart/sac-remote-desktop-handover.desktop, remote login shows a black screen and the journal logs Aborting handover. Do not enable the stock gnome-remote-desktop-handover.service alongside them. Both claim the same D-Bus name, and systemd refuses the second one.

The login screen never appears and /dev/dri is missing

The machine is running the -cloud-amd64 kernel, which has no DRM graphics driver. Reinstall the generic kernel and remove the cloud flavour:

sudo apt-get install --reinstall linux-image-amd64
sudo apt-get purge 'linux-image-*-cloud-amd64' linux-image-cloud-amd64
sudo update-grub
sudo reboot

The RDP client says the credentials are wrong

The client is asking for the RDP credential (Step 5), not your account password. Print it again with sudo sac-remote-desktop credentials.

The login screen does not accept my password

That prompt asks for your account password, the one you set with sudo passwd azureuser. If you forgot it, set it again over SSH.

The client reports a graphics pipeline error

The image refuses older RDP clients that do not advertise the RDP graphics pipeline. With FreeRDP, pass /gfx /bpp:32. Current Windows App, mstsc and Remmina all work.

Cannot connect via SSH

  • Confirm that the network security group allows TCP 22 from your address.
  • Confirm that you are using the private key that matches the public key you gave at deployment.
  • Check in the Azure Portal that the VM is running.

Azure agent not running

systemctl status walinuxagent
sudo systemctl restart walinuxagent

Important notes

  • Two passwords, both yours. The per-VM RDP credential gates the connection before any pixel is drawn; your own account password gates the GNOME login screen. The image ships neither. The first is generated on your machine at first boot, and the second you choose.
  • Remote desktop ships off. A new machine listens on SSH only. The listing does not pre-open 3389 in your network security group.
  • Keep the generic kernel. The -cloud-amd64 flavour has no DRM driver, so the desktop does not start on it.
  • Use an SSH tunnel instead of exposing 3389 to the internet.
  • Google Drive is not available in Files (see Step 7). Every other remote location type (SMB, SFTP, WebDAV, NFS, AFP, FTP, MTP, AFC and OneDrive) works normally, and Google accounts still work in Settings -> Online Accounts for Calendar and Contacts.
  • Debian 13 "trixie" has security support to 30 June 2030.
  • SecureAnyCloud is not affiliated with, endorsed by or sponsored by the Debian Project or the GNOME Foundation. "Debian" is a trademark of Software in the Public Interest, Inc. and "GNOME" is a trademark of the GNOME Foundation; both are used here nominatively to identify the software this image contains.

Support

For assistance with this image, contact SecureAnyCloud support at sales@secureanycloud.com. Support is available 24/7.

Deploy on Azure

Launch Debian 13 with GNOME Desktop on Azure with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure