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