XRDP is an open source server for Microsoft's Remote Desktop Protocol (RDP). It lets you open a graphical Linux desktop from the Remote Desktop client built into Windows, the Windows App on macOS or Remmina on Linux. In this tutorial you will install the lightweight Xfce desktop and XRDP on an Ubuntu 24.04 server, connect through an encrypted SSH tunnel, and limit who can open a remote desktop session.

Prerequisites

To follow this guide you need:

  • A server running Ubuntu 24.04 LTS with at least 2 GB of RAM, for example a CubePath VPS.
  • A non-root user with sudo privileges and a password set. XRDP authenticates with the system password, so key-only SSH users need one (sudo passwd your_user).
  • SSH access to the server from your computer.
  • An RDP client: Remote Desktop Connection (mstsc) on Windows, Windows App on macOS, or Remmina on Linux.

Step 1 - Installing the Xfce desktop

A server image has no graphical environment, and XRDP needs one to start in each session. Xfce is a good fit: it is light, stable, and works well over RDP without the compositing problems of GNOME.

Update the package index and install Xfce:

sudo apt update
sudo apt install xfce4 xfce4-goodies dbus-x11

xfce4-goodies adds a terminal, a text editor and panel plugins, and dbus-x11 provides the session bus launcher the desktop needs. The download is several hundred megabytes. If apt asks which display manager to use, choose either one; XRDP does not use it.

A display manager is not needed on a headless server. Keep the server booting to the text console so it does not start a local graphical login that wastes memory:

sudo systemctl set-default multi-user.target

Step 2 - Installing XRDP

Install the XRDP package from the Ubuntu repositories. It also pulls in xorgxrdp, the Xorg driver XRDP uses to run a real X server for each session:

sudo apt install xrdp

XRDP reads its TLS certificate and key from the files in /etc/ssl, which on Ubuntu are only readable by the ssl-cert group. Add the xrdp system user to that group:

sudo adduser xrdp ssl-cert

Restart the service so the new group membership takes effect, and make sure it starts at boot:

sudo systemctl restart xrdp
sudo systemctl enable xrdp

Check the service and the listening port:

sudo systemctl status xrdp --no-pager
sudo ss -tlnp | grep 3389
● xrdp.service - xrdp daemon
     Loaded: loaded (/usr/lib/systemd/system/xrdp.service; enabled; preset: enabled)
     Active: active (running) since Thu 2026-09-24 10:12:03 UTC; 5s ago
...
LISTEN 0      2                  *:3389             *:*    users:(("xrdp",pid=4127,fd=11))

Step 3 - Telling XRDP to start Xfce

When a user logs in, XRDP runs /etc/xrdp/startwm.sh, which in turn reads the user's ~/.xsession file. Create that file for the user who will connect, logged in as that user (not with sudo):

echo "xfce4-session" > ~/.xsession

Repeat this for every user who needs a remote desktop. To make Xfce the default for users created in the future, place the same file in /etc/skel:

echo "xfce4-session" | sudo tee /etc/skel/.xsession

No restart is needed; the file is read at each login.

Step 4 - Connecting through an SSH tunnel

RDP servers exposed to the internet are scanned and brute-forced constantly. Instead of opening port 3389, keep it closed in the firewall and reach it through SSH, which already has your keys and your hardening.

First make sure UFW allows SSH but not RDP:

sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw status
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)

Port 3389 does not appear, so it is blocked from outside. On your computer, open a tunnel that forwards local port 13389 to port 3389 on the server. A local port other than 3389 avoids a clash with the Remote Desktop service on Windows machines. This works in a Linux or macOS terminal and in PowerShell on Windows 10 and 11:

ssh -N -L 13389:localhost:3389 your_user@your_server_ip

The command prints nothing and keeps running while the tunnel is open. Leave it open and connect your RDP client to localhost:13389:

  • Windows: press Win + R, run mstsc, enter localhost:13389 and click Connect.
  • macOS: in Windows App, add a PC with the address localhost:13389.
  • Linux: install Remmina with sudo apt install remmina, create an RDP connection to localhost:13389.

The client warns that the server certificate cannot be verified, because XRDP uses Ubuntu's self-signed "snakeoil" certificate. That is expected here, since the traffic is already protected by SSH. Accept it and log in with your Linux username and password. The Xfce desktop appears.

Step 5 - Restricting who can log in

By default any local account with a password can open a desktop, including root. XRDP's session manager can limit logins to members of a group. Create the group and add the users who need access:

sudo groupadd tsusers
sudo usermod -aG tsusers your_user

Open the session manager configuration:

sudo nano /etc/xrdp/sesman.ini

In the [Security] section, set these keys to the following values (they already exist in the file):

[Security]
AllowRootLogin=false
MaxLoginRetry=4
TerminalServerUsers=tsusers
TerminalServerAdmins=tsadmins
AlwaysGroupCheck=true

AlwaysGroupCheck=true makes XRDP refuse logins from users who are not in tsusers, instead of ignoring the setting when the group is missing. Restart XRDP:

sudo systemctl restart xrdp

Reconnect as your_user to confirm you still get a desktop. A user outside the group is now rejected after entering the password.

Step 6 - Tuning sessions

When you close the RDP window without logging out, the session keeps running and you reconnect to the same desktop next time. That is convenient, but abandoned sessions hold memory. In the [Sessions] section of /etc/xrdp/sesman.ini you can end disconnected sessions after a while:

sudo nano /etc/xrdp/sesman.ini
[Sessions]
MaxSessions=10
KillDisconnected=false
DisconnectedTimeLimit=3600
IdleTimeLimit=0

With these values a disconnected session is terminated after one hour (3600 seconds), and each server accepts at most 10 simultaneous sessions. Restart XRDP after editing:

sudo systemctl restart xrdp

To log out cleanly, use Log Out from the Xfce menu instead of closing the client window.

If the desktop feels slow on a high-latency link, lower the color depth to 16-bit in the client's display settings and turn off the wallpaper in Xfce's Settings > Desktop. Both reduce the amount of screen data sent.

Troubleshooting

Black or blue screen after login, then the connection closes: the desktop session failed to start. Make sure ~/.xsession exists for that user and contains xfce4-session, then read the session logs:

sudo journalctl -u xrdp -u xrdp-sesman --since "10 minutes ago"
cat ~/.xsession-errors

Login fails immediately with the right password: the user may be logged in to a local graphical session, or may not be in tsusers. Check group membership with groups your_user and the reason in /var/log/xrdp-sesman.log.

The client reports a certificate or security error: confirm the xrdp user is in the ssl-cert group (groups xrdp) and restart the service. Look for Cannot read private key file in /var/log/xrdp.log.

The SSH tunnel command fails with bind: Address already in use: another program uses local port 13389. Pick a different local port, for example -L 23389:localhost:3389, and connect to that port.

Conclusion

You installed Xfce and XRDP on Ubuntu 24.04, reached the desktop over an SSH tunnel without opening port 3389, and limited remote desktop access to a dedicated group with a cap on idle sessions. As next steps, disable password authentication for SSH itself so the tunnel requires a key, install only the graphical applications you actually need, and consider a browser-based gateway such as Apache Guacamole if users should connect without an RDP client.