Creating a headless virtual VNC session (i.e. no monitor plugged in) for Ubuntu 20.04 using GNOME was harder than anticipated. It was easy to set up a local VNC session, but going headless without a dummy adapter AND with the GNOME desktop was a challenge.
Some VNC servers only support local VNC sessions (i.e. controlling the visible logged-in desktop). Others can support virtual (remote) displays that are truly headless. We want the latter. TigerVNC supports virtual displays, is an active successor to TIghtVNC, and is easy to install from the Ubuntu repositories
sudo apt install tigervnc-standalone-server
Setup VNC password for the user.
Test the installation by starting and then killing the server.
vncserver :1 vncserver -kill :1
Configure the VNC Server
We want to run the VNC server as a system service (starts at boot), using GNOME (i.e. not XFCE4). Instructions found in other tutorials might work if you manually start the VNC server, but you will get a black screen if starting it as a service with GNOME (although it works with XFCE4). The fix comes from this post.
Create ~/.vnc/xstartup, edit the file, make executable
cd ~/.vnc pico xstartup
#!/bin/sh [ -x /etc/vnc/xstartup ] && exec /etc/vnc/xstartup [ -r $HOME/.Xresources ] && xrdb $HOME/.Xresources
chmod 755 xstartup
Create /etc/vnc/xstartup, edit the file, make executable. This will create the typical Ubuntu desktop.
sudo mkdir /etc/vnc cd /etc/vnc sudo pico xstartup
#!/bin/sh test x"$SHELL" = x"" && SHELL=/bin/bash test x"$1" = x"" && set -- default vncconfig -iconic & "$SHELL" -l << EOF export XDG_SESSION_TYPE=x11 export GNOME_SHELL_SESSION_MODE=ubuntu dbus-launch --exit-with-session gnome-session --session=ubuntu EOF vncserver -kill $DISPLAY
chmod 755 xstartup
Create /etc/systemd/system/vncserver@.service and start the service
sudo pico /etc/systemd/system/vncserver@.service
[Unit] Description=Start TigerVNC server at startup After=syslog.target network.target [Service] Type=simple User=USERNAME PAMName=login PIDFile=/home/USERNAME/.vnc/%H:%i.pid ExecStartPre=/usr/bin/vncserver -kill :%i > /dev/null 2>&1 ExecStart=/usr/bin/vncserver -fg -depth 24 -geometry 1920x1200 -localhost no :%i ExecStop=/usr/bin/vncserver -kill :%i [Install] WantedBy=multi-user.target
sudo systemctl daemon-reload sudo systemctl enable email@example.com sudo systemctl start vncserver@1 sudo systemctl status vncserver@1
Connect Using Remmina VNC Client
If using Ubuntu 20.04 as the client machine, Remmina (a VNC client) is installed by default. Enter the VNC connection settings under the basic tab (e.g. COMPUTERNAME.local:1, :1 corresponds to the display number above). Enter the SSH settings under the SSH Tunnel tab. Remmina is convenient because it handles the SSH tunnel. As long as the SSH port has been opened, you shouldn’t have to configure anything else (e.g. opening up port 5901 on the server).