Headless Wayland RDP with GNOME Remote Desktop on Ubuntu 24.04
Set up headless multi-user RDP access on Ubuntu 24.04 using GNOME Remote Desktop, following official GNOME documentation. Ansible configuration below.
If you’re working on OpenNebula you’ll need to modify the template first.
Overview
GNOME Remote Desktop provides native RDP support in Ubuntu, making it ideal for:
- Headless VM access via Apache Guacamole
- Multi-user remote login to a graphical desktop
- Hardware-accelerated graphics with virtio-gpu
Ansible Config
# Configure Ubuntu desktop for Guacamole RDP access
# This role sets up a secure RDP connection via GNOME Remote Desktop service
# for seamless integration with Apache Guacamole HTML5 remote desktop gateway.
- name: Install packages
become: true
ansible.builtin.apt:
name: "{{ package_name }}"
autoremove: true
state: present
loop:
- winpr-utils # Required for TLS certificate generation
- gnome-remote-desktop # Provides the remote desktop service
# Packages for hardware-accelerated graphics with virtio-gpu
- mesa-utils
- mesa-vulkan-drivers
- libgl1-mesa-dri
loop_control:
loop_var: package_name
notify:
- Reboot if needed
- name: Allow client to pass locale environment variables and timezone
become: true
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?AcceptEnv'
line: 'AcceptEnv LANG LC_* TZ'
state: present
create: false
notify: restart SSH
- name: Enable PasswordAuthentication for SSH
become: true
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^#?PasswordAuthentication'
line: 'PasswordAuthentication yes'
state: present
create: false
notify: restart SSH
- name: Enable linger for admin user to maintain graphical session after reboot
become: true
command: loginctl enable-linger {{ guacamole_guest_admin_user }}
changed_when: false
- name: Set graphical target as default boot target
become: true
systemd:
name: graphical.target
enabled: true
- name: Remove nomodeset from GRUB to enable graphics driver detection
become: true
lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX_DEFAULT='
line: 'GRUB_CMDLINE_LINUX_DEFAULT="quiet text"'
backrefs: true
- name: Update GRUB configuration to apply boot parameter changes
become: true
command: update-grub
notify:
- Reboot if needed
- name: Apply immediate reboot if required by configuration changes
meta: flush_handlers
# TLS certificate generation for secure RDP connections
# https://gitlab.gnome.org/GNOME/gnome-remote-desktop#tls-key-and-certificate-generation
- name: Generate TLS certificate and key for GNOME Remote Desktop
become: true
command: sudo -u gnome-remote-desktop sh -c 'winpr-makecert -silent -rdp -path ~/.local/share/gnome-remote-desktop tls'
# Configure GNOME Remote Desktop for headless multi-user remote login
# https://gitlab.gnome.org/GNOME/gnome-remote-desktop#headless-multi-user-remote-login
- name: Configure TLS key for RDP connections
become: true
command: sudo grdctl --system rdp set-tls-key ~gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.key
- name: Configure TLS certificate for RDP connections
become: true
command: sudo grdctl --system rdp set-tls-cert ~gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.crt
- name: Set RDP access credentials
become: true
command: sudo grdctl --system rdp set-credentials rdpuser rdppass
- name: Enable interactive input control for RDP sessions
become: true
command: sudo grdctl --system rdp disable-view-only
- name: Enable RDP protocol support in GNOME Remote Desktop
become: true
command: sudo grdctl --system rdp enable
- name: Enable GNOME Remote Desktop service to start at boot
become: true
command: sudo systemctl enable --now gnome-remote-desktop.service
- name: Restart GNOME Remote Desktop service to apply all configurations
become: true
command: sudo systemctl restart --now gnome-remote-desktop.service
Key Steps Explained
1. Package Installation
The winpr-utils package provides winpr-makecert for generating TLS certificates. The Mesa packages enable hardware-accelerated graphics when running on VMs with virtio-gpu.
2. Session Persistence
loginctl enable-linger ensures user sessions survive after logout, which is essential for headless RDP access.
3. Boot Configuration
Setting graphical.target and removing nomodeset from GRUB ensures the system boots into a graphical environment with proper driver detection. Not needed if you started off with a Desktop system rather than installing ubuntu-desktop-minimal over a server install.
4. TLS Certificates
Certificates are generated using winpr-makecert and stored in ~gnome-remote-desktop/.local/share/gnome-remote-desktop/. Running as the gnome-remote-desktop user ensures correct ownership.
5. System-Wide RDP
Using grdctl --system configures the system-wide RDP service for multi-user headless access, as opposed to per-user desktop sharing.
Verifying the Setup
After running the playbook, verify the configuration:
sudo grdctl --system status --show-credentials
You should see:
Overall:
Unit status: active
RDP:
Status: enabled
Port: 3389
TLS certificate: /var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.crt
TLS key: /var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/tls.key
Username: rdpuser
Password: rdppass
macOS RDP Client Fix
If using Windows App (formerly Microsoft Remote Desktop) on macOS, edit your .rdp file:
use redirection server name:i:1
See: https://www.reddit.com/r/Ubuntu/comments/1n8pq1e/rdp_to_ubuntu_from_the_windows_app_on_macos/
Ubuntu 25.10 Considerations
A detailed troubleshooting guide for Ubuntu 25.10 documents some differences that may require changes:
| Aspect | Ubuntu 24.04 | Ubuntu 25.10 |
|---|---|---|
| Certificate tool | winpr-makecert |
OpenSSL (alternative) |
| Certificate path | ~gnome-remote-desktop/.local/share/gnome-remote-desktop/ |
/var/lib/gnome-remote-desktop/ |
| Permissions | Implicit (runs as gnome-remote-desktop user) | May need explicit chmod 600/644 |
OpenSSL Alternative for Certificates
If winpr-utils becomes unavailable or problematic, use OpenSSL instead:
sudo openssl req -newkey rsa:2048 -nodes \
-keyout /var/lib/gnome-remote-desktop/rdp-tls.key \
-x509 -days 365 \
-out /var/lib/gnome-remote-desktop/rdp-tls.crt \
-subj "/CN=$(hostname)"
sudo chown gnome-remote-desktop:gnome-remote-desktop /var/lib/gnome-remote-desktop/rdp-tls.*
sudo chmod 600 /var/lib/gnome-remote-desktop/rdp-tls.key
sudo chmod 644 /var/lib/gnome-remote-desktop/rdp-tls.crt
Approach is fundamentally the same across versions. Test on 25.10 before upgrading production systems.