Guides

xrdp on Ubuntu and Debian: install an RDP desktop (XFCE) on a VPS and fix the black screen

Install xrdp with XFCE on Ubuntu 24.04 or Debian 12/13, add xrdp to ssl-cert, open port 3389 to your IP only or tunnel it over SSH, and fix the black screen.

Published ~10 min read

Short answer: xrdp is an open-source RDP server for Linux. Install it together with a light desktop such as XFCE, and the Remote Desktop client you already have (mstsc on Windows, Windows App on a Mac, Remmina on Linux) logs you in to a graphical session on your Ubuntu or Debian server. The install takes a handful of commands. The part that needs thought is who may reach port 3389.

Debian · Ubuntu · the short version
sudo apt update
sudo apt install -y xfce4 xfce4-terminal xorgxrdp xrdp ufw
sudo adduser xrdp ssl-cert          # lets xrdp read its TLS key
echo xfce4-session > ~/.xsession    # run this as the user who will log in
sudo systemctl restart xrdp
sudo ufw allow OpenSSH              # first, or enabling ufw locks you out
sudo ufw allow from 198.51.100.7 to any port 3389 proto tcp   # your own IP only
sudo ufw enable

Then point an RDP client at the server’s IP address, accept the certificate warning (the certificate is self-signed), and sign in with your Linux username and password on xrdp’s login screen. Below: each step explained, how to keep 3389 closed with an SSH tunnel, and the black-screen fixes.

What xrdp does, and when you do not need it

xrdp speaks the Remote Desktop Protocol on TCP port 3389, checks your password through PAM, and starts a new X session for you: an Xorg server with the xorgxrdp driver, running the desktop you configured. Nothing is mirrored from a physical screen. Every user who logs in gets a desktop of their own, which is the main difference from VNC, where everyone shares one existing screen. If you disconnect without logging out, the session keeps running, and your next login picks it up where you left it.

A Linux server does not need a desktop to be managed. SSH does that job with less memory and less to secure. xrdp earns its place when you need graphical programs on the server: a browser that should browse from the server’s IP, a GUI-only tool, a monitoring or trading app. If that program is Windows software, a Windows VPS is the simpler route, and RDP vs VPS sorts out the terms.

ReleasexrdpDaemon runs ascolord prompt fixedPipeWire sound module
Ubuntu 24.040.9.24user xrdpyes, rule shippedpipewire-module-xrdp
Debian 120.9.21.1user xrdpno, add the rule belowbookworm-backports only
Debian 130.10.1rootyes, rule shippedpipewire-module-xrdp

How do you install xrdp with XFCE?

  1. 1Create a normal user for the desktop

    xrdp accepts root logins by default (AllowRootLogin=true in /etc/xrdp/sesman.ini), but then every browser tab and file manager window runs as root. Log in over SSH and create a regular user with sudo rights instead:

    Debian · Ubuntu
    sudo adduser alice
    sudo usermod -aG sudo alice

    The details, including how to test sudo safely, are in creating a sudo user.

  2. 2Install XFCE and xrdp
    Debian · Ubuntu
    sudo apt update
    sudo apt install -y xfce4 xfce4-terminal xorgxrdp xrdp

    The xfce4 package brings the panel, window manager, file manager and session manager, and pulls in Xorg as a recommended package. It does not install a display manager, which is what you want on a server: the desktop only runs while someone is logged in over RDP. Skip GNOME on a VPS: it needs noticeably more memory and, on Ubuntu, extra session settings before it runs under xrdp.

  3. 3Add the xrdp user to the ssl-cert group

    On Ubuntu 24.04 and Debian 12 the xrdp daemon runs as its own unprivileged user, xrdp. Its TLS key, /etc/xrdp/key.pem, is a link to /etc/ssl/private/ssl-cert-snakeoil.key, which only root and the ssl-cert group may read. Without the group, /var/log/xrdp.log shows Cannot read private key file /etc/xrdp/key.pem: Permission denied, and xrdp cannot offer TLS. Connections then fall back to xrdp’s older and weaker RDP-layer encryption.

    Debian · Ubuntu
    sudo adduser xrdp ssl-cert
    sudo systemctl restart xrdp

    Debian 13’s xrdp runs as root and reads the key anyway, so the step is harmless there.

  4. 4Tell xrdp which desktop to start

    xrdp runs /etc/xrdp/startwm.sh, which on Debian and Ubuntu hands over to /etc/X11/Xsession, and that reads ~/.xsession if it exists. As the user who will log in:

    as alice
    echo xfce4-session > ~/.xsession

    XFCE would usually be picked anyway, but the file keeps the choice explicit if you add another desktop later.

  5. 5Check that xrdp is listening
    Debian · Ubuntu
    sudo systemctl status xrdp --no-pager
    sudo ss -tlnp | grep 3389

    You want active (running) and a line with port 3389 owned by xrdp. If the service failed to start, sudo journalctl -u xrdp -n 30 shows why, and a port held by another program is the usual reason. On Ubuntu Desktop that program is often GNOME’s own Remote Desktop (Settings → System → Remote Desktop), which also serves RDP on 3389. Switch it off there, or run only one of the two.

  6. 6Open port 3389 to your own IP only

    Find your public IP (the What is my IP page shows it) and allow only that address; replace 198.51.100.7 below with it. Allow SSH first, or enabling ufw locks you out. On Debian, install ufw with sudo apt install -y ufw.

    ufw · Debian, Ubuntu
    sudo ufw allow OpenSSH
    sudo ufw allow from 198.51.100.7 to any port 3389 proto tcp
    sudo ufw enable
    sudo ufw status numbered

    The ufw guide covers the defaults and the right order in more detail.

    To confirm that everyone else is shut out, run the open port checker against the server’s IP and port 3389. It connects from our server in Amsterdam, which is not on your allow list, so “no answer” is the result you want.

  7. 7Connect

    On Windows, open Remote Desktop Connection (mstsc) and enter the server’s IP. Accept the warning about the certificate: xrdp uses the self-signed “snakeoil” certificate unless you set your own with certificate= and key_file= in /etc/xrdp/xrdp.ini. xrdp then shows its own login box. Leave the session type on Xorg and enter the Linux username and password. From a Mac, Windows App works the same way.

Safer: keep port 3389 closed and tunnel RDP through SSH

The xrdp versions in Ubuntu and Debian do not support Network Level Authentication. NLA is the check that makes Windows ask for credentials before it shows anything. Whoever reaches xrdp’s port gets its login box and can try passwords against it. If your IP changes, or you work from several places, do not open 3389 at all. Let xrdp listen on localhost only and carry RDP inside SSH instead:

/etc/xrdp/xrdp.ini · [Globals] section
; was: port=3389
port=tcp://.:3389
Debian · Ubuntu
sudo systemctl restart xrdp
sudo ss -tlnp | grep 3389      # now 127.0.0.1:3389
sudo ufw delete allow from 198.51.100.7 to any port 3389 proto tcp
on your computer · PowerShell, macOS or Linux terminal
ssh -N -L 3390:127.0.0.1:3389 alice@203.0.113.10
# leave it running, then connect the RDP client to 127.0.0.1:3390

Use a local port other than 3389, because a Windows PC with Remote Desktop enabled already listens there. xrdp now answers only on the server itself, so nobody on the internet can reach its login box. The only door left is SSH, and with key-only logins, as set up in securing SSH access, that door does not take passwords either.

Why does xrdp show a black screen? Causes in order

A black screen, or a window that closes right after login, means xrdp accepted your password but the desktop did not come up. The logs usually name the reason, so read them before you change anything:

Debian · Ubuntu
sudo tail -n 40 /var/log/xrdp-sesman.log   # session start, PAM, window manager
sudo tail -n 40 /var/log/xrdp.log          # connection, TLS, certificate
tail -n 40 ~/.xsession-errors              # the desktop itself (run as the user)
ls -la ~/.xorgxrdp.*.log                   # Xorg log, one per display (:10, :11 ...)

1. The same user already has a desktop session

This is the most common cause. A user who is still logged in to a desktop elsewhere cannot start a second one cleanly, and the new session stays black or drops after a few seconds. On a VPS that happens after you installed a display manager and logged in on the console, or when an old xrdp session hangs. xrdp hands you back your existing session by default (it matches on user name and colour depth), so a broken one keeps coming back. Find it and end it:

Debian · Ubuntu · from SSH
pgrep -a -u alice 'Xorg|xfce4-session'   # one Xorg per desktop (:10, :11 ...)
sudo kill 12345        # PID of the stale Xorg from the list; its desktop ends with it

To stop this from happening again, log out from the XFCE menu when you are done instead of closing the RDP window. If you would rather have abandoned sessions cleaned up automatically, set KillDisconnected=true and a DisconnectedTimeLimit in seconds (60 or more) in the [Sessions] section of /etc/xrdp/sesman.ini. Note that a disconnected desktop is then gone for good, with any unsaved work in it.

2. The desktop exits right after login

If the session command fails, the RDP window closes or goes black within seconds, and the sesman log says so:

/var/log/xrdp-sesman.log
Window manager (pid 2345, display 10) exited quickly (0 secs). This could indicate a window manager config problem

Check that ~/.xsession contains xfce4-session, that the command exists (command -v xfce4-session), and read ~/.xsession-errors for the error the desktop printed. A ~/.xsession left over from another desktop is a classic culprit.

3. Xorg never starts

If the sesman log reports that the X server could not be started, or the Xorg log ends in an error, check that the driver package is there with dpkg -l xorgxrdp and install it if it is missing. The Xorg log in your home directory names the module that failed to load.

4. Root-owned files in your home directory

Running a graphical program with sudo can leave files such as ~/.Xauthority or parts of ~/.cache owned by root, and the desktop then fails to start for the real user. List them and give them back:

Debian · Ubuntu
sudo find /home/alice -xdev -user root                                   # list them
sudo find /home/alice -xdev -user root -exec chown alice:alice {} +      # hand them back

5. An occasional black screen with a cursor on Ubuntu 24.04

On Ubuntu 24.04 there are reports, mostly from GNOME users, of a random black screen with a working mouse pointer. An xrdp maintainer saw the same symptom on a plain 24.04 console under Xorg, without xrdp involved, which points at the release’s graphics stack. Ending the stuck session as in cause 1 and logging in again clears it.

The “Authentication is required to create a color managed device” prompt

On Debian 12 an XFCE session over xrdp can pop up a password prompt from colord right after login. colord allows these actions without a password only for local sessions, and an RDP session is remote. Ubuntu 24.04 and Debian 13 ship a polkit rule that lets the logged-in user through; on Debian 12, add the same rule yourself. polkit picks up new rule files without a restart:

Debian 12
sudo tee /etc/polkit-1/rules.d/45-xrdp-colord.rules > /dev/null <<'EOF'
polkit.addRule(function (action, subject) {
  var allowed = [
    "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"
  ];
  if (subject.active && allowed.indexOf(action.id) >= 0) {
    return polkit.Result.YES;
  }
});
EOF

Clipboard, file transfer and sound

  • Clipboard: copying text works in both directions out of the box. A helper process, xrdp-chansrv, runs inside your session and handles it. If the clipboard stops working after a reconnect, log out fully and log in again. Check that the helper is running with pgrep -a xrdp-chansrv, and read its log in ~/.local/share/xrdp/xrdp-chansrv.10.log.
  • Files: copied files and drives you share from the client appear under ~/thinclient_drives. To block file transfer, set EnableFuseMount=false in sesman.ini, which also turns off drive sharing. To stop text from leaving the server, use RestrictOutboundClipboard in the same file.
  • Sound: xrdp needs a module that matches your session’s sound server. The packaged one is for PipeWire. Installing XFCE on a bare server often pulls in PulseAudio instead, so check what runs inside the RDP session first.
sound · Ubuntu 24.04, Debian 13
pgrep -a -u "$USER" 'pipewire|pulseaudio'     # inside the RDP session
sudo apt install -y pipewire-audio pipewire-module-xrdp
# then log out completely and connect again

pipewire-audio conflicts with pulseaudio, so apt removes PulseAudio in the same step; the XFCE volume plugin keeps working on PipeWire. On Debian 12 the module only exists in bookworm-backports:

sound · Debian 12
# skip the first line if bookworm-backports is already in your apt sources
echo "deb http://deb.debian.org/debian bookworm-backports main" | sudo tee /etc/apt/sources.list.d/backports.list
sudo apt update
sudo apt install -y pipewire-audio
sudo apt install -y -t bookworm-backports pipewire-module-xrdp

Plain PulseAudio would need pulseaudio-module-xrdp, which Debian does not package, so PipeWire is the easier route. On the client, leave the remote audio setting on “play on this computer”, which is the default.

Make the desktop feel faster

Every frame travels over the internet, so less animation means a snappier session. Turn off XFCE’s compositor, which adds shadows and transparency that RDP then has to transmit:

inside the XFCE session
xfconf-query -c xfwm4 -p /general/use_compositing -s false

On a slow link, lower the colour depth in the client (mstsc: Display tab) and pick a plain wallpaper. Log out of your desktop before you change the colour depth: xrdp matches sessions by user and colour depth, so the new setting starts a second desktop while the old one keeps running. Memory matters more than CPU here: each logged-in desktop holds its own Xorg and session processes, and a web browser inside it needs far more again.

Connecting from a Linux computer

The same steps work when your own machine runs Linux. Remmina is the usual graphical client: sudo apt install remmina remmina-plugin-rdp. On the command line, FreeRDP does the job. The command is xfreerdp from the freerdp2-x11 package on Ubuntu 24.04 and Debian 12, and xfreerdp3 from freerdp3-x11 on Debian 13, which no longer ships FreeRDP 2. Ubuntu 24.04 offers freerdp3-x11 as well, with the same options:

Linux client
xfreerdp /v:203.0.113.10 /u:alice            # Ubuntu 24.04, Debian 12
xfreerdp3 /v:127.0.0.1:3390 /u:alice          # Debian 13, through the SSH tunnel

When the desktop locks you out

A desktop adds things that can break, so keep SSH as your main way in and treat RDP as the extra. On a VMHeaven Ubuntu VPS or Debian VPS, the browser VNC console in the panel shows the server’s screen even when SSH and RDP are both unreachable, and a reinstall from the panel gives you a clean system if an experiment goes too far. For a desktop with a browser in it, pick a plan with memory to spare. The Standard KVM line carries the most vCores per euro and more memory per plan than Hi-CPU at the same price.

Frequently asked

Can I use the Windows Remote Desktop client to connect to Ubuntu?

Yes. Install xrdp and a desktop such as XFCE on the Ubuntu machine, then connect with Remote Desktop Connection (mstsc) to its IP on port 3389 and sign in with your Linux username and password on xrdp's login screen. Ubuntu Server has no desktop of its own, so xrdp alone has nothing to show.

Why do I get a black screen after logging in with xrdp?

Usually the same user already has a desktop session somewhere else, or the command in ~/.xsession is missing or wrong, so the desktop exits at once. Read /var/log/xrdp-sesman.log and ~/.xsession-errors, end the stale session, and put xfce4-session in ~/.xsession.

Is it safe to open port 3389 for xrdp?

Only to addresses you trust. The xrdp versions in Ubuntu and Debian do not support Network Level Authentication, so anyone who reaches the port gets a login screen to guess passwords against. Allow 3389 from your own IP only, or keep it closed and tunnel RDP through SSH.

Related articles

All guides