// linux

VNC

Guide for installing, configuring, troubleshooting, and securing a VNC server on Linux

vnc · remote-desktop · tigervnc · linux · security

Overview

VNC (Virtual Network Computing) provides remote graphical desktop access to Linux servers. It uses the RFB (Remote Framebuffer) protocol to transmit screen updates and receive keyboard/mouse input.

Common VNC Server Implementations

ImplementationDescription
TigerVNCActively maintained, high performance, most recommended
TightVNCOptimized for slow network connections
x11vncShares the existing X display (no virtual display)
TurboVNCOptimized for 3D and video workloads

This cheat sheet focuses primarily on TigerVNC, the most widely used implementation.

How VNC Works

VNC Client (viewer) --> [RFB Protocol / Port 5900+N] --> VNC Server (display :N)
  • Display :1 listens on port 5901
  • Display :2 listens on port 5902
  • Display :0 is typically the physical display

Installation

Ubuntu / Debian

# Install TigerVNC server
sudo apt update
sudo apt install tigervnc-standalone-server tigervnc-common

# Install a desktop environment (if not already installed)
sudo apt install xfce4 xfce4-goodies          # Lightweight
# OR
sudo apt install ubuntu-desktop                 # Full GNOME

RHEL / CentOS / Fedora

# RHEL / CentOS (with EPEL)
sudo dnf install epel-release
sudo dnf install tigervnc-server

# Fedora
sudo dnf install tigervnc-server

# Install a desktop environment
sudo dnf groupinstall "Xfce"                   # Lightweight
# OR
sudo dnf groupinstall "Server with GUI"         # Full GNOME

Arch Linux

sudo pacman -S tigervnc

# Install a desktop environment
sudo pacman -S xfce4 xfce4-goodies

Install x11vnc (Share Existing Display)

# Ubuntu / Debian
sudo apt install x11vnc

# RHEL / CentOS / Fedora
sudo dnf install x11vnc

Basic Usage

Set VNC Password

vncpasswd                                       # Set password for current user
# You'll be prompted to enter and confirm a password
# Optionally set a view-only password when asked

Password is stored in ~/.vnc/passwd.

Start VNC Server

vncserver                                        # Start on next available display
vncserver :1                                     # Start on display :1 (port 5901)
vncserver :2                                     # Start on display :2 (port 5902)
vncserver -geometry 1920x1080                    # Set resolution
vncserver -depth 24                              # Set color depth (8, 16, 24)
vncserver -localhost yes                         # Listen only on localhost (for SSH tunneling)

Stop VNC Server

vncserver -kill :1                               # Kill display :1
vncserver -kill :*                               # Kill all VNC sessions for current user

List Running VNC Sessions

vncserver -list                                  # List active sessions

x11vnc (Share Existing Display)

# Share the current X display
x11vnc -display :0 -auth guess

# With password and forever mode (don't exit after first client disconnects)
x11vnc -display :0 -auth guess -forever -rfbauth ~/.vnc/passwd

# Listen only on localhost
x11vnc -display :0 -auth guess -forever -localhost

Configuration

Key Configuration Files

FilePurpose
~/.vnc/xstartupStartup script — defines which desktop environment to launch
~/.vnc/configDefault VNC server options
~/.vnc/passwdEncrypted VNC password
~/.vnc/*.logSession log files
~/.vnc/*.pidProcess ID files for running sessions

Configure Desktop Environment (~/.vnc/xstartup)

Create or edit ~/.vnc/xstartup:

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec startxfce4

For GNOME:

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec gnome-session

For MATE:

#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec mate-session

Make it executable:

chmod +x ~/.vnc/xstartup

Default Server Options (~/.vnc/config)

Create or edit ~/.vnc/config:

# Display geometry
geometry=1920x1080

# Color depth
depth=24

# Only allow connections from localhost (use with SSH tunnel)
localhost

# Disable clipboard transfer (security)
# SendCutText=0
# AcceptCutText=0

Common vncserver Options

OptionDescription
-geometry WxHSet screen resolution (e.g., 1920x1080)
-depth NColor depth: 8, 16, or 24
-localhost yesAccept connections only from localhost
-rfbport PORTSpecify custom RFB port
-name STRINGSet the desktop name shown in viewer
-fgRun in the foreground (don’t daemonize)
-SecurityTypes TYPESet authentication type (e.g., VncAuth, TLSVnc, None)

Running as a Systemd Service

Create a Systemd Unit File

Create /etc/systemd/system/[email protected]:

[Unit]
Description=Remote desktop service (VNC)
After=syslog.target network.target

[Service]
Type=forking
User=your_username
Group=your_username
WorkingDirectory=/home/your_username
PIDFile=/home/your_username/.vnc/%H:%i.pid

ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill :%i > /dev/null 2>&1 || :'
ExecStart=/usr/bin/vncserver :%i -geometry 1920x1080 -depth 24 -localhost yes
ExecStop=/usr/bin/vncserver -kill :%i

Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target

Replace your_username with the actual user.

Manage the Service

# Reload systemd after creating/editing the unit file
sudo systemctl daemon-reload

# Enable the service to start on boot (display :1)
sudo systemctl enable vncserver@1

# Start the service
sudo systemctl start vncserver@1

# Stop the service
sudo systemctl stop vncserver@1

# Check the service status
sudo systemctl status vncserver@1

# View logs
journalctl -u vncserver@1 -f

SSH Tunneling

VNC traffic is unencrypted by default. Always use SSH tunneling for remote connections.

Create an SSH Tunnel

# From your local machine, forward local port 5901 to remote VNC display :1
ssh -L 5901:localhost:5901 user@remote-server

# Run in the background (no interactive shell)
ssh -L 5901:localhost:5901 -N -f user@remote-server

# Then connect your VNC viewer to localhost:5901

SSH Tunnel with a Jump Host

# Tunnel through a bastion/jump host to reach the VNC server
ssh -L 5901:vnc-server:5901 -J user@jump-host user@vnc-server

Using SSH Config for Persistent Tunnels

Add to ~/.ssh/config:

Host vnc-tunnel
    HostName remote-server
    User your_username
    LocalForward 5901 localhost:5901

Then connect with:

ssh vnc-tunnel
# VNC viewer connects to localhost:5901

Security

Restrict to Localhost Only

Always bind VNC to localhost and use SSH tunneling for remote access:

# Start VNC server bound to localhost
vncserver :1 -localhost yes

Or set in ~/.vnc/config:

localhost

Firewall Rules

If you must expose VNC directly (not recommended), restrict access:

# UFW (Ubuntu/Debian)
sudo ufw allow from 192.168.1.0/24 to any port 5901    # Allow only from LAN
sudo ufw deny 5901                                       # Block all other VNC access

# firewalld (RHEL/CentOS/Fedora)
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.1.0/24" port port="5901" protocol="tcp" accept'
sudo firewall-cmd --reload

# iptables
sudo iptables -A INPUT -p tcp -s 192.168.1.0/24 --dport 5901 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 5901 -j DROP

Enable TLS Encryption

TigerVNC supports TLS for encrypted connections:

# Generate a self-signed certificate
openssl req -x509 -newkey rsa:4096 -keyout ~/.vnc/key.pem -out ~/.vnc/cert.pem -days 365 -nodes

# Start VNC with TLS
vncserver :1 -SecurityTypes TLSVnc -X509Key ~/.vnc/key.pem -X509Cert ~/.vnc/cert.pem

Security Best Practices

  1. Never expose VNC directly to the internet — always use SSH tunneling
  2. Use strong VNC passwords — at least 8 characters with mixed case, numbers, and symbols
  3. Bind to localhost — use -localhost yes to prevent direct remote connections
  4. Keep VNC software updated — apply security patches regularly
  5. Use TLS encryption when SSH tunneling is not an option
  6. Limit users — only run VNC for users who need remote desktop access
  7. Monitor logs — check ~/.vnc/*.log for unauthorized access attempts
  8. Use fail2ban — configure fail2ban to block brute-force attempts on VNC ports

Connecting from Clients

Common VNC Viewers

ViewerPlatformNotes
TigerVNC ViewerLinux, Windows, macOSRecommended, matches TigerVNC server
RealVNC ViewerLinux, Windows, macOS, mobileFree for personal use
RemminaLinuxMulti-protocol (VNC, RDP, SSH)
VinagreLinux (GNOME)Built into GNOME
Screen SharingmacOSBuilt-in VNC viewer

Connect to a VNC Server

# TigerVNC Viewer
vncviewer localhost:5901                         # Connect via SSH tunnel
vncviewer 192.168.1.100:5901                     # Connect directly (LAN only)

# Remmina (from command line)
remmina -c vnc://localhost:5901

macOS Built-in Viewer

# Open Screen Sharing from terminal
open vnc://localhost:5901

Uninstallation

Remove VNC Server

# Stop all running VNC sessions
vncserver -kill :*

# Stop and disable the systemd service
sudo systemctl stop vncserver@1
sudo systemctl disable vncserver@1
sudo rm /etc/systemd/system/[email protected]
sudo systemctl daemon-reload

Remove Packages

# Ubuntu / Debian
sudo apt remove --purge tigervnc-standalone-server tigervnc-common
sudo apt autoremove

# RHEL / CentOS / Fedora
sudo dnf remove tigervnc-server

# Arch Linux
sudo pacman -Rns tigervnc

Clean Up Configuration

# Remove VNC configuration directory
rm -rf ~/.vnc

Troubleshooting

Common Issues

IssueCauseSolution
Black/gray screenMissing or broken xstartupCreate/fix ~/.vnc/xstartup with correct desktop environment
”Connection refused”VNC server not running or wrong portCheck vncserver -list and verify the display number
”Authentication failure”Wrong passwordReset with vncpasswd
Session starts then immediately diesError in xstartup scriptCheck ~/.vnc/*.log for errors
Cannot connect remotelyFirewall blocking or localhost-onlyCheck firewall rules; use SSH tunnel if -localhost yes is set
Poor performance / lagHigh resolution or slow networkReduce geometry, lower color depth, use compression in viewer
”A VNC server is already running”Stale PID file or session still activeKill with vncserver -kill :N or remove stale PID file
Desktop environment not loadingDE not installed or wrong exec commandInstall DE packages; verify the exec command in xstartup

Debugging Steps

# Check VNC server logs
cat ~/.vnc/*.log

# Check if VNC is listening
ss -tlnp | grep 590

# Check if the VNC process is running
ps aux | grep vnc

# Test local connection
vncviewer localhost:5901

# Check systemd service logs
journalctl -u vncserver@1 --no-pager -n 50

Quick Reference

Essential Commands

vncpasswd                                        # Set VNC password
vncserver :1                                     # Start display :1
vncserver :1 -geometry 1920x1080 -localhost yes  # Start with options
vncserver -list                                  # List active sessions
vncserver -kill :1                               # Stop display :1
vncserver -kill :*                               # Stop all sessions

Key Files

~/.vnc/xstartup                                  # Desktop startup script
~/.vnc/config                                    # Default server options
~/.vnc/passwd                                    # VNC password (encrypted)
~/.vnc/*.log                                     # Session logs
/etc/systemd/system/[email protected]           # Systemd service unit

Default Ports

Display :0  -->  Port 5900 (usually physical display)
Display :1  -->  Port 5901
Display :2  -->  Port 5902
Display :N  -->  Port 5900 + N