All articles
TutorialsMay 20, 2026 · 21 min read

Set Up xRDP on Ubuntu for Remote Desktop into a Linux VPS

Set Up xRDP on Ubuntu for Remote Desktop into a Linux VPS

A headless Linux VPS is great for servers, but sometimes you just want a real desktop. A browser to test something, a file manager to drag files around, GIMP for a quick image edit, or a stable scraping/automation session running 24/7. RDP is the cheapest way to get there - the Microsoft Remote Desktop client ships with every Windows install and has free, polished apps on Mac, iOS, and Android.

xRDP is the open-source Linux implementation of the RDP protocol. It bridges any X11 desktop environment (XFCE, MATE, GNOME, KDE) to an RDP session, so you can log in from any RDP client and get a real graphical session on your Ubuntu box.

This guide walks through a production-ready setup on a single VPS: a lightweight desktop, xRDP, a remote-only user, SSH tunneling instead of an open 3389, fail2ban for brute-force protection, and performance tuning that actually moves the needle.

TL;DR

  • Install XFCE on a fresh Ubuntu 22.04 or 24.04 VPS
  • Install and enable xrdp, then tell it to launch XFCE for the session
  • Create a dedicated rdp user and put it in the ssl-cert group
  • Do not open TCP 3389 to the internet - tunnel it over SSH or expose it only on a Tailscale or WireGuard interface
  • Add a fail2ban jail for xRDP
  • Connect with the Microsoft Remote Desktop client from any device

Total time: about 20 minutes.

What You Need

  • A VPS with at least 1 GB RAM (2 GB is more comfortable) running Ubuntu 22.04 or 24.04
  • Root or sudo access
  • An RDP client - mstsc.exe on Windows, Microsoft Remote Desktop on Mac/iOS, Remmina on Linux, or the Microsoft RD app on Android

xRDP itself is light, but the desktop environment matters. XFCE idles around 250 MB and stays snappy on a single vCPU. GNOME is closer to 1.5 GB and will feel sluggish on a small VPS. This guide uses XFCE.

Step 1: Update the System

Always start from a clean baseline.

sudo apt update sudo apt upgrade -y sudo apt install -y curl ufw

If this is a brand new VPS, also walk through SSH hardening with fail2ban before you go any further. Everything below assumes the SSH side is already locked down.

Step 2: Install XFCE

XFCE is the sweet spot for remote desktops - small enough to run on a 1 GB box, complete enough to feel like a real Linux desktop.

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

This pulls in about 700 MB. While it installs, Ubuntu may ask which display manager to use - pick lightdm if prompted, but you won't actually be logging in at the VPS console.

Step 3: Install xRDP

sudo apt install -y xrdp

The installer creates a system user xrdp and starts the service on TCP 3389. Confirm it's running:

systemctl status xrdp

You should see active (running). If it's not, start it:

sudo systemctl enable --now xrdp

Step 4: Tell xRDP to Launch XFCE

By default xRDP launches whatever your shell's ~/.xsession says, which is usually nothing. Tell it explicitly to start XFCE for every session.

Create or replace /etc/xrdp/startwm.sh with:

sudo tee /etc/xrdp/startwm.sh > /dev/null <<'EOF' #!/bin/sh if [ -r /etc/default/locale ]; then . /etc/default/locale export LANG LANGUAGE fi startxfce4 EOF sudo chmod +x /etc/xrdp/startwm.sh

The original Debian script has logic that tries to launch GNOME and falls back through a chain of desktops. Replacing it with startxfce4 removes that guesswork and makes session startup reliable.

Restart xRDP so it picks up the change:

sudo systemctl restart xrdp

Step 5: Create a Dedicated Remote-Only User

Logging in over RDP as your sudo-enabled admin user is sloppy. Create a separate account that's allowed to RDP but not to escalate to root.

sudo adduser rdp sudo adduser rdp ssl-cert

The ssl-cert group lets xRDP read its TLS certificate when the user opens a session - otherwise you get a black screen and the logs complain about /etc/ssl/private/ssl-cert-snakeoil.key permissions.

Set a strong password during adduser. Don't reuse your SSH password. RDP exposes the password to brute force, so use something long and random and store it in a password manager.

If you want this user to also have a sudoers entry for one specific task (say, mounting a shared folder), add a single line via visudo rather than handing them full sudo.

Do not log into xRDP as the same user that already has an active console or SSH session running an X server. xRDP's default `Xorg` backend gets confused when the user already owns a graphical lock - you end up with a blank screen and a session that won't authenticate. One user, one session.

Step 6: Do Not Open Port 3389 to the Internet

This is the single most important step in the guide. The default xRDP install listens on 0.0.0.0:3389. If you open that in your firewall, the entire internet starts brute-forcing your VPS within hours. Every common username and password combination gets tried, all day, every day.

You have three reasonable options. Pick one - never expose 3389 to the internet without one of these.

Option A: SSH Tunnel (Recommended)

Tunnel RDP over your already-hardened SSH connection. xRDP listens only on 127.0.0.1, and your client connects to localhost:3389 after opening the tunnel.

Bind xRDP to localhost only. Edit /etc/xrdp/xrdp.ini and change the port line:

[Globals] port=tcp://127.0.0.1:3389

Restart xRDP:

sudo systemctl restart xrdp

On your local machine, open the tunnel:

ssh -L 3389:127.0.0.1:3389 [email protected]

Now point your RDP client at localhost:3389. Traffic flows over the encrypted SSH tunnel; xRDP has zero exposure on the public interface. Make sure your UFW rules allow SSH but not 3389:

sudo ufw allow 22/tcp sudo ufw enable

Option B: WireGuard or Tailscale

Put the VPS on a private overlay network and let xRDP listen on that interface only. See our guides on Tailscale and WireGuard for the network side.

Once Tailscale is up, find the tailnet IP of the VPS (e.g. 100.x.y.z) and bind xRDP to it:

[Globals] port=tcp://100.x.y.z:3389

UFW stays closed on 3389 for the public interface. Only devices on the tailnet can reach the port.

Option C: IP Allowlist (Last Resort)

If you have a single static office IP and don't want to fiddle with tunnels, allowlist just that one address:

sudo ufw allow from 203.0.113.10 to any port 3389 proto tcp

Be honest with yourself about how static that IP really is. Most home connections rotate addresses periodically, and the day yours flips you'll be locked out.

Step 7: Add a Fail2ban Jail for xRDP

Even with the public port closed, defense in depth is cheap. If you ever flip to Option B or C, fail2ban catches anything that slips through.

Install fail2ban if you haven't already (see our SSH hardening guide for the full setup):

sudo apt install -y fail2ban

xRDP logs to /var/log/xrdp.log. Create /etc/fail2ban/filter.d/xrdp.conf:

[Definition] failregex = ^.*\[ERROR\] authentication failed.*from <ADDR>.*$ ^.*connection refused from <ADDR>.*$ ignoreregex =

Then create /etc/fail2ban/jail.d/xrdp.conf:

[xrdp] enabled = true port = 3389 filter = xrdp logpath = /var/log/xrdp.log maxretry = 4 findtime = 10m bantime = 1h

Reload fail2ban:

sudo systemctl restart fail2ban sudo fail2ban-client status xrdp

Four failed logins in 10 minutes earns an IP a one-hour ban. Adjust to taste.

Step 8: Tune xRDP for Performance

xRDP's defaults are conservative. On a small VPS over a slow link, a few tweaks make the difference between "feels like a desktop" and "feels like a slideshow."

Edit /etc/xrdp/xrdp.ini and look at the [Globals] section:

[Globals] port=tcp://127.0.0.1:3389 crypt_level=high allow_channels=true max_bpp=24 new_cursors=true use_compression=yes

A few notes on what these do:

  • max_bpp=24 caps color depth at 24 bits. Going to 32 doesn't visibly help anything and burns bandwidth. Drop to 16 for laggy mobile connections.
  • use_compression=yes enables bitmap compression. Big win over residential uplinks.
  • crypt_level=high keeps the RDP connection encrypted with TLS even when you tunnel over SSH. Belt and suspenders.

You can also set per-session defaults in the same file under [Xorg] to lower resolution on connect.

On the client side, settings matter just as much. In mstsc.exe:

  • Set the experience to LAN (10 Mbps or higher) only if you actually have it; otherwise pick Broadband High (2 Mbps - 10 Mbps).
  • Disable wallpaper, font smoothing, desktop composition, and visual styles. They look nice and absolutely kill responsiveness.
  • Lower the screen resolution. 1600x900 is the sweet spot - smaller than your local display, still usable.

Apply, restart xRDP, reconnect. The session should feel noticeably more responsive.

Step 9: Make Clipboard and File Sharing Work

Out of the box, clipboard sync between your client and the xRDP session is fragile. A small package fixes it for XFCE:

sudo apt install -y xclip

Then enable the clipboard channel in xrdp.ini (it's on by default in modern builds, but worth confirming):

allow_channels=true

For file transfer, the cleanest path on Windows is mstsc's built-in drive redirection. In the RDP client open Show Options, then Local Resources, then More, and check Drives. The selected drives mount inside the xRDP session under ~/thinclient_drives/. Drag and drop works once you navigate there in Thunar.

On Mac/iOS, the official Microsoft Remote Desktop client supports folder redirection under the connection's Folders tab. Same idea: select a local folder, it appears inside the session.

Step 10: Connect From Each Platform

Windows - press Win+R, type mstsc, hit enter. Server: localhost:3389 if you tunneled over SSH, otherwise the VPS hostname. Username: rdp. Save the connection as a .rdp file once it works.

Mac - install the Microsoft Remote Desktop app from the Mac App Store, click the + button, fill in the PC name, save, double-click to connect.

iOS / iPadOS - same Microsoft Remote Desktop app from the App Store. iPads with a Magic Keyboard or Bluetooth mouse give you a real desktop experience that's genuinely useful for sysadmin work.

Android - the Microsoft RD app on the Play Store works well, especially in landscape on a tablet.

Linux - Remmina is the most polished client. It supports SSH tunneling natively, so you don't have to keep a separate ssh -L running. Set up the connection once and tick the SSH tunnel box.

For full-screen and resolution tips per client, our Connect to RDP From Any Device post covers the GUI details.

Troubleshooting

Black screen after login, then a disconnect. Almost always the ssl-cert group permissions. Run sudo adduser rdp ssl-cert and reconnect.

startxfce4: command not found in ~/.xsession-errors. XFCE didn't install cleanly. Run sudo apt install --reinstall xfce4 and confirm which startxfce4 returns a path.

You can log in once, then it hangs on subsequent connections. A stale session is still bound to the user. SSH in and run sudo pkill -KILL -u rdp, then reconnect.

Two-monitor support is missing. xRDP supports multi-monitor only with Xorg as the backend, which is the default in 22.04+. In your RDP client enable Use all monitors for the remote session.

fail2ban isn't catching anything. Tail /var/log/xrdp.log and confirm the failed-auth format matches the failregex. xRDP's log format changes between versions; adjust the regex if needed and sudo fail2ban-client status xrdp to verify.

The session feels usable for ten seconds then slows to a crawl. Almost always your VPS is swapping. Run htop and check the swap line. Either upgrade to more RAM or drop XFCE for LXQt, which idles around 120 MB.

Going Further

  • Use Wayland-friendly clients. If you eventually want GNOME or KDE Plasma over RDP, look at GNOME Remote Desktop or KDE's built-in RDP server - both are newer and use FreeRDP under the hood.
  • Hide xRDP behind Apache Guacamole. Our Guacamole guide puts a web-based RDP gateway in front so you can connect from any browser without an RDP client.
  • Layer in Beszel for monitoring. RDP sessions are CPU- and RAM-hungry. Knowing when the box is about to thrash is half the battle.
  • Snapshot the VPS before installing. Most providers offer one-click snapshots. Take one immediately after Step 4 - if you ever break X11, rolling back is faster than debugging.

That's the whole stack. Twenty minutes of setup gets you a real Linux desktop reachable from anywhere - encrypted, brute-force protected, and snappy enough to actually work in.


Need a VPS with enough RAM to host a remote desktop comfortably? Our Linux plans include fast NVMe storage, IPv6, and snapshots out of the box. See the options.