Wednesday, 6 May 2026

GUI Access to Remote Server using VNC

 To view a graphical desktop on a remote server (rather than just having command line access), I do the following.....

Install tightvncserver

apt install tightvncserver

Set Password

run 'vncserver', and enter a password when prompted.

Then shutdown the server with vncserver -kill :1

Set up user desktop

Create /home/graham/.vnc/xstartup which contains:
#!/bin/bash
unset SESSION_MANAGER
unset DBUS_SESSION_BUS_ADDRESS

# Ensure a clean environment for XFCE
export XDG_CURRENT_DESKTOP="XFCE"
export XDG_MENU_PREFIX="xfce-"

# Add this to prevent X from trying to use hardware acceleration
export LIBGL_ALWAYS_SOFTWARE=1

# Start the environment
[ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup
[ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources

autocutsel -fork
exec dbus-launch --exit-with-session startxfce4


Start vncserver on boot using a system service

Create /etc/systemd/system/vncserver@.service

[Unit]
Description=Start TightVNC Server at Startup
After=syslog.target network.target
[Service]
Type=forking
User=graham
Group=users
WorkingDirectory=/home/graham
PIDFile=/home/graham/.vnc/%H:%i.pid
ExecStartPre=-/usr/bin/vncserver -kill :%i > /dev/null 2>&1
ExecStart=/usr/bin/vncserver -depth 24 -geometry 1280x800 -localhost -extension GLX :%i
ExecStop=/usr/bin/vncserver -kill :%i
[Install]
WantedBy=multi-user.target

The -extension GLX is important because this suddenly stopped working on Ubuntu 24.04 - it seemed that probing the nvidia hardware was causing security issues which crashed the vnc server.


Set it going with:

systemctl daemon-reload
systemctl enable vncserver@1.service
systemctl restart vncserver@1.service


Set up Client Machine

On the machine you want to use as the client, add a small function to ~/.bashrc:
function start_vnc_tunnel() {
    SSH_USER="$1"
    SERVER_IP="$2"
    LOCAL_PORT="5901"

    echo "Starting SSH tunnel to $SERVER_IP..."
    ssh -L "$LOCAL_PORT":localhost:"$LOCAL_PORT" -N "$SSH_USER"@"$SERVER_IP" &
    SSH_PID=$!
    
    # Give the tunnel a moment to establish
    sleep 2 

    echo "Attempting to connect VNC viewer to localhost:$LOCAL_PORT..."
    # The script now waits here for the vncviewer to close
    vncviewer localhost:"$LOCAL_PORT"

    echo "VNC viewer closed. Killing tunnel (PID: $SSH_PID)."
    kill "$SSH_PID"
    exit 0
}

Then add aliases to use it to access the machines you are interested in such as:

alias oracvnc='start_vnc_tunnel graham orac.local'