NoMachine with XFCE Desktop on Headless VPS: Complete Setup Guide

Why Use a VPS as Your Development Environment
Running a full Linux desktop on a remote VPS can be surprisingly practical — especially when paired with NoMachine for a fast graphical interface. Here’s why many developers prefer this setup:
- Always on: Your environment stays online 24/7, ready for builds, automation, or background jobs.
- Access from anywhere: Connect from your laptop, tablet, or even another VPS with full desktop continuity.
- Cost-efficient: Many VPS providers offer great performance for the price — and when you factor in electricity, cooling, and hardware depreciation, a VPS can be cheaper than maintaining a local workstation.
- Stable and reliable: You’re protected from power outages, local hardware failures, or unstable home networks.
- Isolated workflows: Each VPS can host a different project stack or experimental environment, keeping your local system clean.
- Lightweight client usage: Since all the heavy lifting happens remotely, you can use a modest laptop or even a Chromebook to access a high-performance dev box.
This setup is particularly appealing to developers who need persistent access to container clusters, cloud tooling, or build pipelines, without leaving their machines running all day.
Why NoMachine?
There are many ways to connect to a remote Linux desktop — VNC, RDP, X2Go, and others — but NoMachine stands out for a few key reasons:
- Exceptional performance: NoMachine’s proprietary NX protocol delivers smooth video and low latency even over slower connections. It supports adaptive compression, multi-threaded encoding, and UDP fallback for streaming-like responsiveness.
- Simple setup: Unlike VNC or X2Go, NoMachine doesn’t require setting up display ports or complicated SSH tunnels. Installation and connectivity work out of the box.
- Full desktop experience: Clipboard sharing, file transfers, and audio forwarding all work natively — no plugins or extensions required.
- Cross-platform: Clients are available for Linux, macOS, Windows, iOS, and Android — making it easy to connect from anywhere.
- Security built in: NX sessions are fully encrypted end to end. You can also restrict access by IP, disable password logins, or run over SSH for maximum control.
- Headless compatibility: NoMachine handles dummy displays gracefully, making it one of the few remote-desktop systems that work reliably on headless servers without a physical GPU.
In short: NoMachine offers a native, high-performance desktop experience without the complexity of configuring multiple services like VNC, XRDP, or X2Go.
Who This Guide Is For
This tutorial is written for intermediate Linux users — anyone comfortable with the terminal, SSH, and basic system administration. You don’t need prior experience with X11 or NoMachine, but you should know how to edit files with nano
or vim
and understand how to restart services.
Table of Contents
Prerequisites
Step 1: Initial VPS Setup
Step 2: Install XFCE Desktop Environment
Step 3: Install NoMachine Server
Step 4: Configure Virtual Displays
Step 5: Create Display Configuration Scripts
Step 6: Set Up Autostart Configuration
Step 7: Configure NoMachine and LightDM
Step 8: Connect with NoMachine Client
Running NoMachine Over SSH
Enabling Key-Based Authentication for NX Protocol
Troubleshooting
Additional Tips
Summary
Prerequisites
- A headless VPS running Ubuntu 24.04 LTS
- Root or sudo access
- SSH access to the server
- NoMachine client installed locally (Download here)
Note: This tutorial was tested on a Hostinger VPS, which offers fair pricing and reliable performance. We are not affiliated with Hostinger — the same procedure should work on any Ubuntu 24.04 VPS provider.
Step 1: Initial VPS Setup
1.1 Update System Packages
sudo apt update && sudo apt upgrade -y
1.2 Create a User Account
sudo adduser yourusernamesudo usermod -aG sudo yourusername
1.3 Configure Swap Memory
Swap memory helps prevent out-of-memory errors when running a desktop environment.
Create a 15 GB Swap File
sudo fallocate -l 15G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
swapon --show
free -h
Make Swap Persistent
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
Tune Swappiness (Optional)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
Step 2: Install XFCE Desktop Environment
2.1 Install XFCE and LightDM
sudo apt install -y xfce4 xfce4-goodies xfce4-session lightdm
When prompted, choose LightDM as your display manager.
Why XFCE?
It’s lightweight, stable, and ideal for remote or low-resource systems.
2.2 Install Virtual Display Support
sudo apt install -y xserver-xorg-video-dummy x11-xserver-utils
2.3 Set Default Session for LightDM
sudo nano /etc/lightdm/lightdm.conf
Add:
[Seat:*]
autologin-session=xfce
autologin-user=yourusername
autologin-user-timeout=0
Why autologin is required: Without autologin, LightDM doesn’t start a display session on headless systems, causing NoMachine to fail. Autologin ensures an XFCE session exists for NoMachine to attach to.
Step 3: Install NoMachine Server
3.1 Download NoMachine
cd /tmp
wget https://download.nomachine.com/download/8.14/Linux/nomachine_8.14.2_1_amd64.deb
3.2 Install
sudo dpkg -i nomachine_*.deb
sudo apt install -f -y
3.3 Verify Service
sudo systemctl status nxserver
Step 4: Configure Virtual Displays
4.1 Create Xorg Config Directory
sudo mkdir -p /etc/X11/xorg.conf.d
4.2 Add Dummy Display Config
sudo nano /etc/X11/xorg.conf.d/10-dummy.conf
Paste the following configuration:
Section "Device"
Identifier "Configured Video Device"
Driver "dummy"
VideoRam 256000
EndSection
Section "Monitor"
Identifier "Configured Monitor"
HorizSync 5.0 - 1000.0
VertRefresh 5.0 - 200.0
Modeline "1920x1080" 148.50 1920 2008 2052 2200 1080 1084 1089 1125 +hsync +vsync
Modeline "3840x2160" 533.00 3840 3888 3920 4000 2160 2163 2168 2222 +hsync -vsync
EndSection
Section "Screen"
Identifier "Default Screen"
Monitor "Configured Monitor"
Device "Configured Video Device"
DefaultDepth 24
SubSection "Display"
Depth 24
Modes "1920x1080" "3840x2160" "1680x1050" "1600x900" "1280x1024"
EndSubSection
EndSection
4.3 Reboot
sudo reboot
About the Display Scripts
Because a VPS has no physical display, X11 must emulate one. The scripts below automate display setup and resolution switching:
set-resolution.sh
runs automatically at login (or via autostart). It ensures that virtual screens (DUMMY0
,DUMMY1
) have the right modes and resolutions.switch-display.sh
is an optional interactive helper for changing layouts (single Full HD, dual displays, or 4K) without editing configs or restarting the session.
If you ever see a black screen, running ~/set-resolution.sh fhd
via SSH often restores the display instantly.
Step 5: Create Display Configuration Scripts
5.1 set-resolution.sh
nano ~/set-resolution.sh
Add:
#!/bin/bash
export DISPLAY=:0
sleep 2
setup_custom_modes() {
if xrandr | grep -q "DUMMY0 connected"; then
if ! xrandr | grep -q "1920x1080_60.00"; then
xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
xrandr --addmode DUMMY0 1920x1080_60.00
xrandr --addmode DUMMY1 1920x1080_60.00
fi
if ! xrandr | grep -q "3840x2160_60"; then
xrandr --newmode "3840x2160_60" 533.00 3840 3888 3920 4000 2160 2163 2168 2222 +hsync -vsync
xrandr --addmode DUMMY0 3840x2160_60
xrandr --addmode DUMMY1 3840x2160_60
fi
fi
}
setup_custom_modes
MODE="${1:-fhd}"
case $MODE in
fhd|1080|fullhd)
xrandr --output DUMMY0 --mode 1920x1080_60.00 --primary
xrandr --output DUMMY1 --off
;;
4k|2160)
xrandr --output DUMMY0 --mode 3840x2160_60 --primary
xrandr --output DUMMY1 --off
;;
dual|2)
xrandr --output DUMMY0 --mode 1920x1080_60.00 --primary
xrandr --output DUMMY1 --mode 1920x1080_60.00 --right-of DUMMY0
;;
*)
echo "Usage: $0 [fhd|4k|dual]"
exit 1
;;
esac
exit 0
Make it executable:
chmod +x ~/set-resolution.sh
5.2 switch-display.sh
nano ~/switch-display.sh
Add:
#!/bin/bash
setup_custom_modes() {
if xrandr | grep -q "DUMMY0 connected"; then
if ! xrandr | grep -q "1920x1080_60.00"; then
xrandr --newmode "1920x1080_60.00" 173.00 1920 2048 2248 2576 1080 1083 1088 1120 -hsync +vsync
xrandr --addmode DUMMY0 1920x1080_60.00
xrandr --addmode DUMMY1 1920x1080_60.00
fi
if ! xrandr | grep -q "3840x2160_60"; then
xrandr --newmode "3840x2160_60" 533.00 3840 3888 3920 4000 2160 2163 2168 2222 +hsync -vsync
xrandr --addmode DUMMY0 3840x2160_60
xrandr --addmode DUMMY1 3840x2160_60
fi
fi
}
setup_custom_modes
clear
echo "1) 4K | 2) Dual 1080p | 3) Single 1080p | 4) Exit"
read -p "Choice: " c
case $c in
1) xrandr --output DUMMY0 --mode 3840x2160_60 --primary; xrandr --output DUMMY1 --off;;
2) xrandr --output DUMMY0 --mode 1920x1080_60.00 --primary; xrandr --output DUMMY1 --mode 1920x1080_60.00 --right-of DUMMY0;;
3) xrandr --output DUMMY0 --mode 1920x1080_60.00 --primary; xrandr --output DUMMY1 --off;;
*) exit 0;;
esac
Make it executable:
chmod +x ~/switch-display.sh
Step 6: Set Up Autostart Configuration
mkdir -p ~/.config/autostart
nano ~/.config/autostart/setup-resolutions.desktop
[Desktop Entry]
Type=Application
Name=Setup Display Resolutions
Exec=/home/yourusername/set-resolution.sh fhd
Terminal=false
X-GNOME-Autostart-enabled=true
Step 7: Configure NoMachine and LightDM
sudo nano /usr/NX/etc/node.cfg
Set:
DefaultDesktopCommand "/etc/X11/Xsession xfce4-session"
Restart:
sudo /usr/NX/bin/nxserver --restart
sudo systemctl restart lightdm
Step 8: Connect with NoMachine Client
- Open the NoMachine client.
- Click Add → NX protocol.
- Enter your VPS IP (default port 4000).
- Provide username and password.
- Connect — you should see your XFCE desktop.
Running NoMachine Over SSH
Running NoMachine over SSH can improve security but slightly reduces performance because:
- SSH tunnels block UDP acceleration
- Adds extra encryption overhead
- May increase latency
For best performance, use NX and restrict IP access with UFW. Use SSH mode when you need a single-port secure tunnel.
Enabling Key-Based Authentication for NX Protocol
1. Generate a Key Pair
ssh-keygen -t rsa -b 4096 -m PEM -f ~/nx_key
2. Add Public Key to Server
mkdir -p ~/.nx/config
cat ~/nx_key.pub >> ~/.nx/config/authorized.crt
chmod 600 ~/.nx/config/authorized.crt
3. Configure Server
sudo nano /usr/NX/etc/server.cfg
Add:
AcceptedAuthenticationMethods NX-private-key, NX-password
Restart NoMachine:
sudo /usr/NX/bin/nxserver --restart
4. Configure Client
In the client connection, choose NX → Key-based authentication, then select your private key.
5. Notes
.nx/config/authorized.crt
must have correct permissions- Public key format must be OpenSSH
- Works across free and enterprise versions (some UI differences)
Troubleshooting
1. Black Screen After Login
ps aux | grep xfce4-session
DISPLAY=:0 xrandr | grep " connected"
~/set-resolution.sh fhd
sudo systemctl restart lightdm
2. Wrong Desktop Environment Loads
grep "DefaultDesktopCommand" /usr/NX/etc/node.cfg
grep "autologin-session" /etc/lightdm/lightdm.conf
Then restart services.
3. Session Freezes or Crashes
DISPLAY=:0 xrandr
ps aux | grep xfce4-session
mv ~/.config/xfce4 ~/.config/xfce4.backup
4. NoMachine Server Not Starting
sudo systemctl status nxserver
sudo systemctl start nxserver
sudo systemctl enable nxserver
5. Display Resolution Not Persisting
Check:
cat ~/.config/autostart/setup-resolutions.desktop
chmod +x ~/set-resolution.sh
~/set-resolution.sh fhd
6. set-resolution.sh: Command not found
Ensure Exec path is absolute in autostart entry.
7. PulseAudio/Audio Issues
pulseaudio --check
pulseaudio --start
Additional Tips
Change resolution anytime:
~/set-resolution.sh fhd
~/set-resolution.sh 4k
~/switch-display.sh
Check logs:
tail -100 ~/.nx/server.log
sudo tail -100 /usr/NX/var/log/server.log
Firewall:
sudo ufw allow 4000/tcp
sudo ufw enable
Disable root login:
sudo nano /usr/NX/etc/server.cfg
EnableRootLogin 0
Summary
You’ve successfully:
- Installed XFCE on a headless Ubuntu VPS;
- Configured dummy X11 displays;
- Installed and secured NoMachine;
- Enabled autologin and automated resolution setup;
- Hardened security with optional SSH and NX key-based authentication.
Remote-ready. Scalable. Future-proof.
Partner with Amplifi Labs to create cloud environments that empower your developers anywhere.
Start Your Project: contact us!