VNC lets you open a remote graphical desktop on an Ubuntu server. It is useful when you need a lightweight remote desktop for administration tools, IDEs, lab systems, or applications that need an X session.
The safest practical setup is to run TigerVNC with XFCE, bind the VNC server to localhost only, and connect through an SSH tunnel. This keeps the VNC port off the network while still letting you use a VNC viewer from your local machine.
This guide configures a VNC display for a normal Linux user, starts it manually for testing, then converts it into a systemd service so it can start after reboot. The package commands were validated on Ubuntu 25.04. The same package names are available on supported Ubuntu releases such as Ubuntu 22.04 and Ubuntu 24.04, but package versions may differ.
:1 maps to TCP port 5901, display :2 maps to 5902, and so on. This guide uses display :1 and keeps it bound to 127.0.0.1 for SSH tunneling.
Quick Command Summary
| Task | Command |
|---|---|
| Install TigerVNC and XFCE | sudo apt install tigervnc-standalone-server tigervnc-common dbus-x11 xfce4-session xfce4-panel xfce4-settings xfdesktop4 xfwm4 xfce4-terminal |
| Set VNC password | vncpasswd |
Start VNC display :1 |
vncserver -localhost yes -geometry 1280x800 -depth 24 :1 |
| List VNC sessions | vncserver -list |
Stop VNC display :1 |
vncserver -kill :1 |
| Check listening port | `ss -ltnp |
| Create SSH tunnel | ssh -L 5901:127.0.0.1:5901 user@server_ip |
| Enable systemd service | sudo systemctl enable --now [email protected] |
| Check service status | systemctl status [email protected] --no-pager |
Prerequisites
You need:
- An Ubuntu server or desktop system.
- A non-root user for the VNC desktop.
- SSH access to the server if you plan to use the secure tunnel method.
sudoprivileges to install packages and create the systemd service.
If you are preparing a minimal Ubuntu server and need XFCE separately, see install XFCE desktop on Ubuntu. If you prefer RDP instead of VNC, compare this with install XRDP with XFCE4 on Ubuntu. For Red Hat based systems, see configure VNC server in RHEL 8.
1. Install TigerVNC and XFCE Packages
Update the package index:
sudo apt updateInstall TigerVNC, DBus support, and a minimal XFCE session:
sudo apt install tigervnc-standalone-server tigervnc-common dbus-x11 xfce4-session xfce4-panel xfce4-settings xfdesktop4 xfwm4 xfce4-terminalThe command below was tested with apt simulation on Ubuntu 25.04 to validate package names and dependencies without changing the test host:
apt install -s tigervnc-standalone-server tigervnc-common dbus-x11 xfce4-session xfce4-panel xfce4-settings xfdesktop4 xfwm4 xfce4-terminalTested output:
Installing:
dbus-x11 xfce4-panel xfce4-terminal
tigervnc-common xfce4-session xfdesktop4
tigervnc-standalone-server xfce4-settings xfwm4
Installing dependencies:
elementary-xfce-icon-theme libtumbler-1-0t64 light-locker
exo-utils libutempter0 light-locker-settings
greybird-gtk-theme libxfce4panel-2.0-4 lightdm
libdbus-glib-1-2 libxfce4ui-2-0 lightdm-gtk-greeter
libexo-2-0 libxfce4ui-common python3-psutil
libexo-common libxfce4util-bin thunar-data
libfile-readbackwards-perl libxfce4util-common tigervnc-tools
libgarcon-1-0 libxfce4util7 tumbler
libgarcon-common libxfce4windowing-0-0 tumbler-common
libgarcon-gtk3-1-0 libxfce4windowing-common xfce4-helpers
libgtk-layer-shell0 libxfconf-0-3 xfconf
liblightdm-gobject-1-0 libxklavier16 xfdesktop4-data
libthunarx-3-0 libxpresent1 xiccd
Summary:
Upgrading: 0, Installing: 48, Removing: 0, Not Upgrading: 51The package availability was also checked directly:
apt-cache policy tigervnc-standalone-server tigervnc-common xfce4 dbus-x11Tested output:
tigervnc-standalone-server:
Installed: (none)
Candidate: 1.14.1+dfsg-1
Version table:
1.14.1+dfsg-1 500
500 http://archive.ubuntu.com/ubuntu plucky/universe amd64 Packages
tigervnc-common:
Installed: (none)
Candidate: 1.14.1+dfsg-1
Version table:
1.14.1+dfsg-1 500
500 http://archive.ubuntu.com/ubuntu plucky/universe amd64 Packages
xfce4:
Installed: (none)
Candidate: 4.20
Version table:
4.20 500
500 http://archive.ubuntu.com/ubuntu plucky/universe amd64 Packages
dbus-x11:
Installed: (none)
Candidate: 1.16.2-2ubuntu1
Version table:
1.16.2-2ubuntu1 500
500 http://archive.ubuntu.com/ubuntu plucky/main amd64 PackagesIf you want the full XFCE desktop and extra plugins, install xfce4 xfce4-goodies instead of the smaller XFCE package list. On a server, the smaller list is usually enough for a VNC desktop.
2. Use a Normal User for the VNC Session
Do not run your daily VNC desktop as root. Use an existing user or create a dedicated user. For a broader account setup guide, see create user in Linux and adduser command examples.
sudo adduser vncuserSwitch to that user before creating the VNC password and startup file:
su - vncuserIf you need to grant administrative access later, use sudo deliberately instead of running the entire graphical session as root. For sudo-user setup, see add user to sudo group in Linux.
3. Set the VNC Password
Run vncpasswd as the user who will own the VNC session:
vncpasswdYou will be prompted for a password. TigerVNC stores the encrypted password under the user's ~/.vnc directory.
Example prompt:
Password:
Verify:
Would you like to enter a view-only password (y/n)? nThe view-only password is optional. Use it only when you want someone to observe the desktop without controlling it.
4. Configure the XFCE Startup File
Create the VNC startup script:
mkdir -p ~/.vnc
nano ~/.vnc/xstartupAdd this content:
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec dbus-launch --exit-with-session startxfce4Make it executable:
chmod +x ~/.vnc/xstartupThe startup script syntax was validated with sh -n on the test host:
sh -n /tmp/glc-vnc-test/xstartup
ls -l /tmp/glc-vnc-test/xstartup
cat /tmp/glc-vnc-test/xstartupTested output:
-rwxr-xr-x 1 root root 111 Jun 7 22:11 /tmp/glc-vnc-test/xstartup
#!/bin/sh
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS
exec dbus-launch --exit-with-session startxfce4dbus-launch comes from the dbus-x11 package. Without it, some desktop components may start with missing session-bus features.
5. Start the VNC Server Manually
Start display :1 and bind it to localhost only:
vncserver -localhost yes -geometry 1280x800 -depth 24 :1Important options:
| Option | Meaning |
|---|---|
-localhost yes |
Listen only on 127.0.0.1, so clients must connect through SSH tunneling or locally |
-geometry 1280x800 |
Set the virtual desktop resolution |
-depth 24 |
Use 24-bit color depth |
:1 |
Start VNC display 1, which maps to TCP port 5901 |
List running VNC sessions:
vncserver -listStop the session when testing is complete:
vncserver -kill :16. Check the Listening VNC Port
After starting display :1, check TCP port 5901:
ss -ltnp | grep 5901If the server was started with -localhost yes, the listener should be on 127.0.0.1:5901 or [::1]:5901, not 0.0.0.0:5901.
The test host did not have VNC running, but the listener check command was validated with active TCP listeners:
ss -ltnp | grep LISTEN | headTested output:
LISTEN 0 4096 127.0.0.54:53 0.0.0.0:* users:(("systemd-resolve",pid=362,fd=17))
LISTEN 0 128 127.0.0.1:6012 0.0.0.0:* users:(("sshd-session",pid=13436,fd=9))
LISTEN 0 4096 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1606,fd=3),("systemd",pid=1,fd=505))
LISTEN 0 4096 *:1313 *:* users:(("hugo",pid=87638,fd=4))For remote access troubleshooting, see test SSH connection commands, test port connectivity in Linux, and check open ports in Linux.
7. Connect Through an SSH Tunnel
From your local computer, create an SSH tunnel to the Ubuntu server:
ssh -L 5901:127.0.0.1:5901 vncuser@server_ipKeep that SSH session open. Then open your VNC viewer on your local computer and connect to:
127.0.0.1:5901This works because your local port 5901 is forwarded over SSH to 127.0.0.1:5901 on the Ubuntu server. For more tunneling patterns, see SSH port forwarding and SSH tunnel examples. If you connect often, simplify the client side with an SSH config file and key-based login from SSH key generation examples.
8. Create a systemd Service for VNC
A systemd service makes the VNC session easier to start, stop, and enable at boot. Create a template unit as root:
sudo nano /etc/systemd/system/[email protected]Add this content. Replace vncuser with your Linux username:
[Unit]
Description=TigerVNC server for display :%i
After=network.target
[Service]
Type=forking
User=vncuser
Group=vncuser
WorkingDirectory=/home/vncuser
PIDFile=/home/vncuser/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i
ExecStart=/usr/bin/vncserver -localhost yes -geometry 1280x800 -depth 24 :%i
ExecStop=/usr/bin/vncserver -kill :%i
[Install]
WantedBy=multi-user.targetReload systemd and start display :1:
sudo systemctl daemon-reload
sudo systemctl enable --now [email protected]Check the service:
systemctl status [email protected] --no-pagerStop or restart it when needed:
sudo systemctl restart [email protected]
sudo systemctl stop [email protected]For more systemd background, see systemd tutorial for beginners and systemctl service listing commands.
9. Check Firewall Rules
If you use -localhost yes and connect through SSH tunneling, you normally do not need to open port 5901 in UFW. You only need SSH access to the server.
Check UFW status:
sudo ufw status verboseTested output:
Status: inactiveIf UFW is active, allow SSH:
sudo ufw allow OpenSSHAvoid exposing VNC directly to the internet. If you intentionally run VNC without localhost-only binding on a trusted private network, restrict the source IP:
sudo ufw allow from CLIENT_IP to any port 5901 proto tcpThat direct-port approach is less secure than SSH tunneling and should not be your default. If SSH is exposed to the network, consider hardening it with Fail2ban for SSH.
10. Troubleshooting Common VNC Problems
| Problem | What to check |
|---|---|
| VNC viewer cannot connect | Confirm the SSH tunnel is still open and the viewer is connecting to 127.0.0.1:5901 |
| Port 5901 is not listening | Run vncserver -list, check systemctl status [email protected], and inspect ~/.vnc/*.log |
| VNC shows a blank or gray screen | Check ~/.vnc/xstartup, confirm it is executable, and confirm XFCE packages are installed |
| Service fails after reboot | Check username, home directory, PIDFile, and /usr/bin/vncserver path in the unit file. See VNC server service failed because a configured resource limit was exceeded for a related systemd failure pattern |
| Direct connection fails but SSH tunnel works | VNC may be correctly bound to localhost only; use the tunnel method |
| Authentication fails | Re-run vncpasswd as the VNC user |
Check the VNC log files:
ls -l ~/.vnc
cat ~/.vnc/*.logCheck service logs:
journalctl -u [email protected] -n 50 --no-pagerFor journald usage, see journalctl command examples.
Frequently Asked Questions
1. Which VNC server should I use on Ubuntu?
TigerVNC is a practical choice for Ubuntu servers because it provides a standalone VNC server, vncpasswd, and systemd-friendly service management.2. Which desktop environment works well with VNC on Ubuntu?
XFCE is commonly used with VNC because it is lighter than a full GNOME desktop and works well inside a virtual VNC display.3. Which port does VNC display :1 use?
VNC display :1 listens on TCP port 5901. Display :2 uses 5902, display :3 uses 5903, and so on.4. Should I expose VNC port 5901 to the internet?
No. A safer setup is to start VNC with localhost-only binding and connect through an SSH tunnel. Open the VNC port directly only on a trusted network and only when you understand the risk.5. How do I connect to an Ubuntu VNC server securely?
Run ssh -L 5901:127.0.0.1:5901 user@server from the client, then connect your VNC viewer to 127.0.0.1:5901.6. How do I make the VNC server start after reboot?
Create a systemd template unit such as [email protected], reload systemd, then enable the display instance with systemctl enable --now [email protected].Summary
To configure a VNC server on Ubuntu, install TigerVNC and XFCE, set a VNC password for a normal user, create ~/.vnc/xstartup, start vncserver on display :1, and connect through an SSH tunnel to 127.0.0.1:5901. For persistent sessions, create a [email protected] systemd template and enable [email protected].
For security, keep VNC bound to localhost and avoid exposing port 5901 directly to the internet.

