I recently worked on a project that required me to run a program that required a GUI to run. This was a bit of a challenge because I was working on a remote server that did not have a physical display (it was “headless”). After many hours of searching/trying, I found a solution that worked. The following are my notes on how to get it working; I hope it helps you if you are in a similar situation!

Note: I have seen a few other people using programs like TeamViewer to access a remote server with a virtual desktop. I personally never got this working because it requires a physical display to be connected to the server, but it may work for you.

## Installation & Setup

### Install TigerVNC on the server

sudo apt install tigervnc-standalone-server -y


TigerVNC is just one of many VNC servers available. I tried several and found it to be the easiest to setup and use.

### Start the VNC server

When you start the VNC server, you will be prompted to set a password. This password will be used to connect to the server from a client.

You can also optionally choose to set

• a virtual display number, e.g. :9 (default is :1)
• a “geometry” for the screen (e.g. 1920x1080)
# create a virtual display (#9) with a screen size of 1920x1080
vncserver -localhost no -geometry 1920x1080 :9


The final output should be something like:

New 'MACHINE:9 (USER)' desktop at :9 on machine MACHINE


Once the display is created, you can connect to it using a VNC client.

## Headless Linux Desktop Environment

If you are connecting to a Linux server without a physical display, you will need to install a dummy XServer for the VNC server to use.

sudo apt install xterm xserver-xorg-video-dummy


## Viewing the VNC display

To view the VNC display, you will need a VNC client. There are many available, select the one that works best for you. I personally use the built in one on Mac. Instructions below:

### Mac VNC Viewer

You need to forward the port of the VNC server (5909 above) to your local machine over SSH, and have a stable connection open. Then you can open the viewer with:

open vnc://localhost:5909


Note: the port number is 5900+N where N is the display number you chose when starting the VNC server.

## Programmatic Access to the Virtual Display

In order for programs to access the virtual display, you need to set the DISPLAY environment variable to the virtual display number (e.g. :9).

export DISPLAY=:9


With this set, you can run code that requires a display (e.g. matplotlib, ai2thor, etc.) without ever needing to physically interact with the server/machine. Super useful for working on the cloud!

Note: Within your code itself, you may also need to set the DISPLAY environment variable to the corresponding display number to get it to run correctly (e.g., in Python: os.environ['DISPLAY'] = ':9').

## Troubleshooting / Tips

Fixing issues with the virtual screen

### Status of all VNC displays

You can check the status of the VNC server and all virtual displays with:

vncserver -list


The following is an example of the output with a stale screen:

TigerVNC server sessions:

X DISPLAY #	PROCESS ID
:9	30309 (stale)


### Kill the virtual display

If the virtual display is stale, you can kill it with:

vncserver -kill :9


### Change the password

If you need to change the password, run:

vncpasswd