XRDP

Debian Host

  • Step 1: Install Xfce4 and xRDPFirst, open your terminal and install the desktop environment and xRDP packages (these examples use Debian/Ubuntu-based distributions):
    sudo apt update
    sudo apt install xfce4 xfce4-goodies xrdp -y
    sudo apt install xorgxrdp xserver-xorg-core -y
  • Step 2: Configure the Desktop Session. You need to tell the xRDP server to load the Xfce desktop environment instead of the default Linux desktop. Set Xfce4 as the default for your active user, then make the file executable:
    echo "xfce4-session" > ~/.xsession
    chmod +x ~/.xsession
  • Step 3: Edit the xRDP Startup ScriptTo prevent session dropouts, update the global xRDP configuration file:Open the file with your preferred text editor, comment out the last 2 lines and add as follows:
    sudo nano /etc/xrdp/startwm.sh
    # test -x /etc/X11/Xsession && exec /etc/X11/Xsession
    # exec /bin/sh /etc/X11/Xsession
    startxfce4
    exit 0
  • Step 4: Add the xRDP User to the SSL Cert Group. On some systems (like newer Debian versions), the xrdp user needs permission to read the SSL certificates, otherwise, you might experience black screen issues:
    sudo adduser xrdp ssl-cert
  • Step 5: Enable the Service:
    sudo systemctl enable xrdp
    sudo ufw allow 3389
  • Step 6: Restart the Service and open the Firewall. Restart the xRDP service to apply all configuration changes:
    sudo systemctl restart xrdp
    sudo ufw allow 3389
  • Step 7: You can now open the Remote Desktop Connection app on Windows or the Microsoft Remote Desktop app on Linux. Enter your Linux computer's IP address and log in using your standard Linux username and password.
  • You might also want to disable IPv6, edit /etc/sysctl.conf:
    net.ipv6.conf.all.disable_ipv6=1

Windows 11 Client

  • Open the built-in Remote Desktop Connection
  • Disable Persistent Bitmap Caching?
    • Click Show Options at the bottom
    • Switch to the Experience tab
    • Uncheck the box for Persistent bitmap caching and try logging in
  • Log Out of the Local Machine. If you are logged into the physical Debian machine (or a local VM console) with the same user account, the remote RDP session will fail instantly. Go to the physical monitor/console of your Debian host and completely Log Out of the desktop session.
  • Create a SSH tunnel with a different port than 3389 on the client and port 3389 on the host

Self-signed certificates

  • If you get a xrdp certificate mismatch

Trust the Existing Self-Signed Certificate

  • Launch your Remote Desktop Connection and enter the server's hostname.
  • Click View Certificate on the security warning prompt.
  • Go to the Details tab and click Copy to File.
  • Save the .cer file to your local computer.
  • Double-click the saved .cer file, click Install Certificate, choose Local Machine, and select Place all certificates in the following store. Browse and pick the Trusted Root Certification Authorities store, then finish the import.

Hostname changed

  • If the hostname has changed you need to re-issue the self-signed certificate:
    sudo make-ssl-cert generate-default-snakeoil --force-overwrite

Using Xvnc backend

My server Olympus does not allow to connect despite of countless attempts to find the culprit of Permission denied errors. Since it's the same debian version like my server Hestia I assume there is an incompatibility with the display hardware or it's firmware. I finally found a way to connect through the Xvnc backend (instead of Xorg).

  • Original search term: cannot open virtual console 2, but this answer comes after several failures.
  1. Completely Wipe the Modified Global Scripts. Overwriting global configuration structures can trap xRDP in an infinite loop. Reverting the global script to its native behavior allows you to handle everything safely within your specific user profile.
    • Run this over SSH to restore the stock startwm.sh configuration
      sudo apt-get install --reinstall xrdp
  2. Isolate the D-Bus Session Daemon. Standard users under Debian 12 require an isolated message bus instance (dbus-launch) when launching a graphical interface inside an unprivileged virtual frame. Without it, the environment crashes silently into a black void and drops the connection.
    • Install the missing D-Bus utility core package via SSH:
      sudo apt update
      sudo apt install -y dbus-x11
    • Next, rewrite your user account's personal .xsession file from scratch to hook directly into the new bus:
      rm -f ~/.xsession
      nano ~/.xsession
    • Paste this explicit configuration sequence:
      #!/bin/sh
      export XDG_SESSION_TYPE=x11
      export XDG_CURRENT_DESKTOP=XFCE
      export XDG_MENU_PREFIX=xfce-
      
      # Spawn an isolated remote session D-Bus pipeline
      eval $(dbus-launch --sh-syntax --exit-with-session)
      
      exec xfce4-session
    • Save the file (Ctrl+O, Enter, Ctrl+X) and set the execution flag:
      chmod +x ~/.xsession
  3. Change Polkit Permissions for Remote Standard Users. Debian's local security policy (Polkit) blocks remote non-root users from claiming network or display profiles managed by systemd.
    • Create a dedicated exception rule file:
      sudo nano /etc/polkit-1/localauthority/50-local.d/45-allow-colord.pkla
    • Paste this exact permission block inside:
      [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
    • Save and close the file.
  4. Set backend default. Find the line autorun= in file /etc/xrdp/xrdp.ini and change it to:
    autorun=Xvnc
  5. Restart services and Test the Xvnc Path. Flush the underlying active sessions and trigger a complete daemon reload
    sudo systemctl daemon-reload
    sudo systemctl restart xrdp
    sudo loginctl terminate-user $USER
  6. Open the Windows 11 Remote Desktop Client (mstsc) and connect. Choose Xvnc on the drop-down menu and type your standard username. The isolated D-Bus pipeline will now safely bypass systemd's local hardware locks and successfully display your XFCE desktop environment.

Automatically start session on Windows client

  • Create a windows batch file and save it's shortcut to the desktop. Content of the file:
    @echo off
    :: bco, 2026-08-16
    :: establish a SSH connection with tunnel to your server
    start wsl ssh -p <ssh-port> -L <external-rdp-port>:localhost:3389 <domain-name-or-ip>
    
    :: Wait for 5 seconds
    timeout /t 5 /nobreak
    
    :: open a RDP session
    start mstsc /v:localhost:<external-rdp-port>

Fix registry entries of RDP client

  • Search term: where does rdp for windows keep the list of connections
  • The native Windows Remote Desktop Connection (mstsc.exe) stores its list of previous connections in the Windows Registry under HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client, split into a recent history list and a permanent record of servers accessed. It also saves connection configurations and recent taskbar shortcuts in specific user folders.
  • Registry Locations
    • Recent 10 Connections (MRU0 to MRU9): HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Default
    • All Previously Connected Servers: HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers (contains individual subkeys for each host with username hints)
  • File and Jump List Locations
    • Default RDP File: %USERPROFILE%\Documents\default.rdp (a hidden file storing settings for the most recent or default session)
    • Taskbar Jump Lists: %APPDATA%\Microsoft\Windows\Recent\AutomaticDestinations\ (stores pinned and recent RDP launch history)
    • Saved Credentials: Windows Credential Manager under TERMSRV/<remote-computer-name>

Trouble Shooting

  • To check which display drivers are installed and currently active in Linux, open your terminal and run
    lspci -k | grep -EA3 'VGA|3D|Display'
    1. Unset Active Environment Variables (Most Common Fix)When logging in physically, Debian sets parameters like XDG_RUNTIME_DIR. If xrdp inherits these values during a remote session, it halts on a black screen. Open a terminal on the Debian machine and edit the startup script:bash sudo nano /etc/xrdp/startwm.sh. Scroll down and insert the following two unset commands:
      # test -x /etc/X11/Xsession && exec /etc/X11/Xsession
      # exec /bin/sh /etc/X11/Xsession
      unset DBUS_SESSION_BUS_ADDRESS
      unset XDG_RUNTIME_DIR
    2. Save and restart the service:
      sudo systemctl restart xrdp
    3. Disconnect and Log Out of the Physical Monitor
    4. Clear Local Display Configurations. Occasionally, the physical display's multi-monitor layout profile or specific resolution data gets cached in XFCE, causing the RDP connection to format blindly.Clear the hardware-specific panel mapping configuration for XFCE by running this command in terminal:
      rm -f ~/.config/xfce4/xfconf/xfce-perchannel-xml/displays.xml
    5. Try connecting via Windows 11 RDP again to force XFCE to re-detect your RDP window parameters dynamically.
    6. Switch from Xorg to Xvnc (Alternative Pipeline). If your physical machine's GPU drivers (especially closed-source Nvidia drivers) refuse to play nicely with xorgxrdp, switching to a VNC-backed server profile usually bypasses the graphics lock completely. On Debian, install the TigerVNC backend:
      sudo apt install tigervnc-standalone-server -y
      sudo systemctl restart xrdp
    7. When you launch Remote Desktop Connection from Windows 11, instead of using the default session choice, look at the xrdp login window dropdown and change the Session type from Xorg to Xvnc or VNC-any.
    8. Check which packages are installed
      apt list --installed xrdp*
  • Methods to Force and View the RDP Certificate
    1. Method 1: Connect via IP Address (Quickest)Open the Remote Desktop Connection client (mstsc).Type the server's IP address instead of its computer name or domain name.Click Connect. Connecting via IP bypasses the matching hostname verification and forces the untrusted or viewable certificate dialog to pop up, enabling the View certificate link.
    2. Method 2: Clear Saved RDP Registry SettingsPress Win + R, type regedit, and press Enter.Navigate to: HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers. Locate the subfolder matching the target server name or IP that is suppressing your prompt.Delete that specific server key/folder.Re-launch Remote Desktop and initiate a fresh connection to force the new certificate prompt to appear.
  • Grant XRDP Access to the Video Card. If your Debian 12 machine has a dedicated or integrated GPU (or virtualized GPU drivers like VMware/VirtualBox guest additions), XRDP needs explicit rights to touch the render pipes.
    sudo adduser xrdp video
    sudo adduser xrdp render
  • Fix Xorg Session Permissions. By default, Debian 12 restricts non-console users from starting an X-server. Even if you updated Xwrapper.config earlier, systemd's local display policies can still block it. Open or create the Xwrapper configuration file, ensure it contains only these two lines, removing everything else:
    sudo nano /etc/X11/Xwrapper.config
    textallowed_users=anybody
    needs_root_rights=no
  • Regenerate the System-Wide Display Script. If previous configuration edits broke the structure of the startup sequence, XRDP will instantly close. Let's force it to cleanly execute D-Bus. Run and edit the bottom of the file
    sudo nano /etc/xrdp/startwm.sh
    unset DBUS_SESSION_BUS_ADDRESS
    unset XDG_RUNTIME_DIR
    export $(dbus-launch)
    startxfce4