All systems operational Your IP: 216.73.216.190 info@cloudhosting.lv +371 66 66 29 69 Client area

← All questions

Remote Desktop on Ubuntu 24.04 with xrdp and Xfce

Most work on a Linux server is better done over SSH. A graphical desktop costs RAM you are paying for, widens the attack surface and lags on anything that redraws. Sometimes it is the right answer anyway. Here is how to run Xfce on Ubuntu 24.04 over RDP without leaving a login prompt facing the internet.

First check that you actually need one

A desktop is justified when a browser has to run from inside the network, an appliance UI on a private VLAN say, or a GUI tool has no command line equivalent. Lighter options cover much of that. For the browser case:

ssh -D 1080 alice@vps.example.com

That is a SOCKS5 proxy on your own machine: point Firefox at 127.0.0.1:1080 and the traffic leaves from the server while your laptop renders. For a single program, ssh -X needs xauth and X11Forwarding yes on the server plus an X server on your side, XQuartz on macOS or VcXsrv on Windows; it suits one window, nothing that animates. RDP earns its place when you want a session you can disconnect from and return to.

What a desktop costs in RAM

Rough numbers. An idle Xfce session over xrdp with a terminal open sits at 400 to 500 MB, counting Xorg, the session and the xrdp helpers. Firefox with five tabs adds 800 MB to 1.5 GB and grows through the day. GNOME Shell would want 1.2 GB for the shell alone without a GPU, which is why this guide uses Xfce.

So 2 GB is the floor for light admin work, 4 GB realistic once a browser is involved, and each extra user costs roughly another browser. Watch vCPU as well, since without a GPU the processor draws every pixel. Our VPS plans take more RAM later, so start modest and measure with free -m under real use. If this becomes somebody's daily workstation, a dedicated server suits it better.

Install Xfce, not a full desktop

sudo apt update
sudo apt install --no-install-recommends xfce4 xfce4-terminal dbus-x11 x11-xserver-utils

In 24.04 the xfce4 metapackage recommends desktop-base, tango-icon-theme, thunar-volman, xfce4-notifyd and xorg. Skipping them leaves no X server at this step, which is fine if you carry straight on, because xorgxrdp arrives with xrdp next and depends on xserver-xorg-core. dbus-x11 provides dbus-launch, which the Xsession scripts fall back to when no session bus is running.

Do not install xubuntu-desktop, ubuntu-desktop or a display manager here: with no physical console to log in at, lightdm or gdm3 would only hold memory.

xrdp with an Xfce session

sudo apt install xrdp
dpkg -l xorgxrdp

Ubuntu 24.04 ships xrdp 0.9.24, which everything below assumes. Do not use --no-install-recommends here: without xorgxrdp, one of its recommends, xrdp quietly falls back to Xvnc sessions, which look and behave differently. The dpkg -l line confirms it arrived.

Three things are left to you. First, the daemon must read the TLS key, so it needs the ssl-cert group:

id xrdp
sudo adduser xrdp ssl-cert
sudo systemctl restart xrdp

Without it the client connects, negotiates and drops at once, and /var/log/xrdp.log shows it failing to open /etc/ssl/private/ssl-cert-snakeoil.key.

Second, root logins. The 0.9 series ships AllowRootLogin=true in the [Security] section of /etc/xrdp/sesman.ini, so on any image with a root password set, root can sign in over RDP. Read the line, then turn it off:

sudo grep -n AllowRootLogin /etc/xrdp/sesman.ini
sudo sed -i 's/^AllowRootLogin=true/AllowRootLogin=false/' /etc/xrdp/sesman.ini
sudo systemctl restart xrdp-sesman

Third, tell the session what to start. /etc/xrdp/startwm.sh ends by calling its own wm_start, which on Debian and Ubuntu sources /etc/X11/Xsession, and Xsession runs ~/.xsession if it exists. Per user:

printf '#!/bin/sh\nexec /usr/bin/xfce4-session\n' > ~/.xsession
chmod +x ~/.xsession

The chmod is tidiness rather than a requirement: /etc/X11/Xsession.d/50x11-common_determine-startup runs a non executable ~/.xsession through your login shell instead of skipping it. To set the session for everyone, replace the wm_start line near the end of startwm.sh with exec startxfce4.

The polkit prompts older guides warn about, the colour managed device and the repository refresh, need colord, PackageKit and an authentication agent, none of them present here. If an inherited image throws them at you, the .pkla fix does nothing on 24.04: polkit 124 dropped that layer, and rules are JavaScript in /etc/polkit-1/rules.d/.

Stop the desktop from suspending your server

Xfce's log out dialog takes its Suspend and Hibernate buttons from systemd-logind, and one careless click puts a VPS off the network until somebody with console access wakes it. Mask the targets and logind reports them unavailable:

sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target

Keep 3389 off the public internet

RDP ports are scanned continuously, and xrdp authenticates real system accounts through PAM, so an exposed 3389 is one weak password away from a shell. Bind the daemon to loopback, in the [Globals] section of /etc/xrdp/xrdp.ini:

port=tcp://127.0.0.1:3389
sudo systemctl restart xrdp
sudo ss -tlnp | grep 3389

That must show 127.0.0.1 only. Then tunnel in:

ssh -N -L 13389:127.0.0.1:3389 alice@vps.example.com

Point the RDP client at localhost:13389; Windows often has 3389 bound.

If a tunnel is impractical, restrict the port at the firewall instead. First put xrdp back on the public address, because a daemon bound to loopback has no socket for the rule to protect: set port=3389 and restart. Then allow SSH before enabling ufw, or the default deny incoming policy locks you out of a machine with no console:

sudo ufw allow OpenSSH
sudo ufw allow from 203.0.113.10 to any port 3389 proto tcp
sudo ufw enable
sudo ufw status numbered

Only worth doing with genuinely static addresses, since a whole residential ISP range is no restriction. Either way, put SSH itself on keys with password authentication disabled: it is now the front door.

Clipboard, sound and client drives

The text clipboard works both ways with no configuration, through xrdp-chansrv, one process per session; if pgrep -a xrdp-chansrv returns nothing, reconnect. Copying from a Linux app that fills only the PRIMARY selection, highlight to copy and middle click to paste, does not reach Windows, which needs a real ctrl+c.

Sound goes through PipeWire, and pipewire-module-xrdp comes in with xrdp's recommends, so it is already installed. It still needs a PipeWire session with pipewire-pulse under your own user, which a server image may lack, so add pipewire pipewire-pulse wireplumber if you want audio. The pulseaudio-module-xrdp other guides name is not in the Ubuntu archive.

Client drives are redirected by default, because EnableFuseMount defaults to true, and they appear in ~/thinclient_drives, the shipped FuseMountName having no leading slash. The mount dies with the session, so never point a backup at it. To turn it off, set EnableFuseMount=false in section [Chansrv] of /etc/xrdp/sesman.ini, where it ships commented out, then restart xrdp-sesman.

Sessions, and what to read when it breaks

A disconnected session keeps running with everything open in it, and three abandoned sessions with a browser each will finish off a small VPS. In /etc/xrdp/sesman.ini, section [Sessions]:

KillDisconnected=true
DisconnectedTimeLimit=7200
IdleTimeLimit=0
MaxSessions=10

Values are in seconds, DisconnectedTimeLimit is ignored unless KillDisconnected is true, the trap in older write ups, anything under 60 is raised to 60, and both work only with xorgxrdp sessions.

When it misbehaves, read these in order:

sudo systemctl status xrdp xrdp-sesman
sudo tail -n 50 /var/log/xrdp.log
sudo tail -n 50 /var/log/xrdp-sesman.log
tail -n 50 ~/.xsession-errors

A blue xrdp screen and an immediate disconnect after correct credentials means the session command failed, and ~/.xsession-errors names it, usually ~/.xsession pointing at a binary that is not installed, or an error inside the file. A black screen with a live cursor means the session started but no window manager did. No login window at all is a firewall or binding question, back to ss -tlnp. A drop right after the TLS handshake is usually the ssl-cert group.

Last, keyboard layout. xrdp takes it from the client, and when it guesses wrong setxkbmap lv or setxkbmap ru fixes that login. The permanent fix is /etc/xrdp/xrdp_keyboard.ini, which maps RDP layout IDs to XKB layouts for xorgxrdp sessions; the km-*.ini files older articles name are the Xvnc path. Russian is there as rdp_layout_ru=0x00000419; for Latvian add rdp_layout_lv=0x00000426 to [default_rdp_layouts] and rdp_layout_lv=lv to [default_layouts_map], then restart.

Once it works, try not to live in it: every hour the desktop sits idle with a browser open is memory doing nothing. If you would rather someone else ran it, our engineers keep this setup in our own Riga data centre and are reachable around the clock through IT support.

Rather have us run it for you?
VPS. NVMe virtual servers, live in under a minute.
Learn more

Ready to start?

Deploy in minutes or talk to an engineer about what fits your project.