Configure xrdp and TigerVNC on Rocky Linux 9

Install a GNOME desktop and configure secure RDP or VNC access on Rocky Linux 9.

xrdp

TigerVNC

RHEL 9 Multiuser VNC Access

Scope

This guide configures a GNOME desktop on Rocky Linux 9 and provides two independent remote-access options:

  • xrdp: Connect with a standard RDP client, including Windows Remote Desktop Connection.
  • TigerVNC: Create a virtual desktop and reach it through an SSH tunnel with a VNC viewer.

Choose the protocol your clients require. Running both is possible, but it adds services and accounts that must be maintained.

The original article targeted CentOS Linux 7 and 8. CentOS Linux 8 reached end of life in December 2021, and CentOS Linux 7 reached end of life in June 2024. Migrate those systems instead of exposing obsolete installations to a network.

The commands below use a Rocky Linux 9 host, an example remote user named remoteuser, and a trusted LAN subnet of 192.168.2.0/24. Replace those values for your environment.

Prepare the Desktop

Update the host and install the GNOME server environment:

sudo dnf upgrade --refresh -y
sudo dnf group install -y "Server with GUI"

List the installed desktop session names. The TigerVNC configuration later in this guide uses the gnome session:

ls -1 /usr/share/xsessions/

Setting the graphical target is optional for a headless remote-desktop server. Enable it when the machine should also show a local graphical login after boot:

sudo systemctl set-default graphical.target

Create a dedicated account if one does not already exist, then assign a strong Linux password:

sudo useradd --create-home remoteuser
sudo passwd remoteuser

Do not run an xrdp or VNC desktop as root.

Option 1: Configure xrdp

xrdp listens for RDP connections on TCP 3389. Its upstream project recommends the xorgxrdp backend for the best experience. On Rocky Linux 9, the packages are available from EPEL.

Enable EPEL and Install xrdp

Enable Rocky Linux’s CodeReady Builder equivalent and EPEL, then install xrdp, its X.Org backend, and its SELinux policy:

sudo dnf install -y dnf-plugins-core
sudo dnf config-manager --set-enabled crb
sudo dnf install -y epel-release
sudo dnf install -y xrdp xorgxrdp xrdp-selinux

Start xrdp and enable it at boot:

sudo systemctl enable --now xrdp
sudo systemctl status xrdp --no-pager

The packaged configuration supplies the session startup scripts. Do not add exec gnome-session to /etc/xrdp/xrdp.ini; that file configures the RDP listener and connection modules rather than the desktop startup command.

Restrict the Firewall Rule

Permit RDP only from the trusted LAN. Confirm that the active network interface uses the public zone before applying this example:

sudo firewall-cmd --get-active-zones
sudo firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.2.0/24" port port="3389" protocol="tcp" accept'
sudo firewall-cmd --reload
sudo firewall-cmd --zone=public --list-rich-rules

Do not forward TCP 3389 directly from the public internet. Use a VPN, an RD Gateway, or another authenticated access layer for connections from outside the trusted network.

Connect with RDP

On Windows, open Remote Desktop Connection:

mstsc.exe

Enter the Rocky Linux host’s private address and sign in as remoteuser. Select Xorg on the xrdp login screen if the session type is shown. Use the Linux account password, not a VNC password.

Avoid signing in to the local GNOME console and xrdp with the same account at the same time. GNOME services tied to one user session can conflict and produce an immediate disconnect or a blank desktop.

Verify that the server is listening:

sudo ss -lntp | grep ':3389'

Option 2: Configure TigerVNC

TigerVNC creates a separate virtual desktop. The current service uses /etc/tigervnc/vncserver.users to map display numbers to Linux users. Do not copy or edit the vendor vncserver@.service unit.

Install TigerVNC

Install the server package:

sudo dnf install -y tigervnc-server

If this host has an old custom unit from an earlier CentOS guide, preserve it as a backup so the packaged unit takes precedence:

sudo test ! -e /etc/systemd/system/vncserver@.service || sudo mv /etc/systemd/system/vncserver@.service /etc/systemd/system/vncserver@.service.legacy
sudo systemctl daemon-reload

Map the User to a Display

Open the user-mapping file:

sudoedit /etc/tigervnc/vncserver.users

Map display :1 to the example user:

:1=remoteuser

Display :1 normally uses TCP port 5901. Each additional user needs a unique display number.

Configure the Virtual Desktop

Open the default configuration:

sudoedit /etc/tigervnc/vncserver-config-defaults

Add these settings:

session=gnome
geometry=1920x1080
localhost
alwaysshared

session must match a desktop file in /usr/share/xsessions without the .desktop suffix. The localhost setting prevents direct network connections to the VNC port; clients will use an encrypted SSH tunnel.

Set the VNC password as the mapped user and restore the expected SELinux labels:

sudo -iu remoteuser vncpasswd
sudo restorecon -RFv /home/remoteuser/.vnc /etc/tigervnc

The VNC password is separate from the Linux login password. Decline a view-only password unless it is specifically required.

Start the VNC Service

Enable the service for display :1:

sudo systemctl enable --now vncserver@:1.service
sudo systemctl status vncserver@:1.service --no-pager
sudo ss -lntp | grep ':5901'

Because the server accepts VNC connections only on loopback, do not open TCP 5901 in firewalld.

Connect Through SSH

From the client computer, create an SSH tunnel and leave the command running:

ssh -N -L 5901:127.0.0.1:5901 remoteuser@server.example.com

Replace server.example.com with the server’s address. In the VNC viewer, connect to 127.0.0.1:5901. The SSH session encrypts the network traffic and forwards it to the VNC listener on the server.

Verification

Check the enabled services and their current state:

systemctl is-enabled xrdp vncserver@:1.service
systemctl is-active xrdp vncserver@:1.service

Display the listening ports:

sudo ss -lntp | grep -E ':(3389|5901)\b'

With the configuration in this guide, xrdp should listen on the host network and VNC should listen only on 127.0.0.1 or ::1.

Troubleshooting

xrdp Shows a Black Screen or Disconnects

Confirm that the packages and services are healthy:

rpm -q xrdp xorgxrdp xrdp-selinux
sudo journalctl -u xrdp -u xrdp-sesman -b --no-pager

Log the same user out of the local graphical console, then try again. Also confirm that Xorg is selected at the xrdp login screen and that the user’s home directory is writable.

TigerVNC Fails to Start

Inspect the service and user-session logs:

sudo systemctl status vncserver@:1.service --no-pager
sudo journalctl -u vncserver@:1.service -b --no-pager

Confirm that :1=remoteuser exists in /etc/tigervnc/vncserver.users, the user has run vncpasswd, and the configured session exists:

grep -F ':1=remoteuser' /etc/tigervnc/vncserver.users
test -f /usr/share/xsessions/gnome.desktop && echo 'GNOME session found'
sudo -iu remoteuser test -r /home/remoteuser/.vnc/passwd && echo 'VNC password found'

TigerVNC cannot start a virtual desktop for a user who is already logged in to another graphical session. Use a dedicated remote account or log that user out before starting the service.

SELinux Blocks a Service

Keep SELinux enforcing. Inspect recent denials before changing policy:

sudo ausearch -m AVC,USER_AVC -ts recent

First restore file labels and confirm that xrdp-selinux is installed. Do not disable SELinux or generate a broad local policy merely to hide a configuration error.

Remove Access

Disable the services when remote desktop access is no longer required:

sudo systemctl disable --now xrdp vncserver@:1.service

Remove the restricted xrdp firewall rule:

sudo firewall-cmd --permanent --zone=public --remove-rich-rule='rule family="ipv4" source address="192.168.2.0/24" port port="3389" protocol="tcp" accept'
sudo firewall-cmd --reload
Licensed under CC BY-NC-SA 4.0
Last updated on Thursday, September 24, 2026
comments powered by Disqus