Have you ever got to a point while working on a project where you absolutely had to run a graphical user interface (GUI) application when you only have access to a headless device? This is an issue that one of our engineers Chris faced a while back while working on the Festive Lighting project
, where the software to control the lights only had a GUI version.
One solution to this problem lies in running the application on an X11 Window System and accessing it via VNC, and that's what today's post is about!
To get started, you will need an account for balenaCloud
. If you are new to the balena ecosystem, take a look at the introduction
first, as the initial setup of your account and provisioning a device is outside the scope of this guide.
The goal for this project is to deploy a multi-container
project on balenaCloud where we will run a sample GUI application (for this example, a calculator) and access it via VNC.
We won't get into detail on how to create an application on balenaCloud or how to provision a device as it is all well explained in the getting started guide
, but if you ever have any questions please let us know on our forums
Downloading and running the application
The blue button pictured will download a .zip file containing the project files, but if you're familiar with Git you can use
git clone in the usual way.
Pushing the code to your device
We will first push the code to the device without changing any configuration in order to make sure everything is working.
For this, we will use the balena cli
tool, where you can push the code by running
balena push <ApplicationName>
in the same folder as the project. You can read more about the CLI here
If everything worked OK, you'll see the unicorn 🦄:
Go back to the dashboard and you’ll be able to see the status of your device downloading and installing everything.
If everything is up and running correctly, you will be able to see a log message saying that
x11vnc are both running. Good job, now let's go ahead and try to connect to the device and use the calculator.
In order to connect to the device and use the calculator, you will need to download a VNC
client. There are many VNC viewer clients out there, but for this tutorial, we'll use RealVNC viewer
Once VNC Viewer is installed, open it and connect to the **on port 8080**. A few things to keep in mind is that initially, you will only be able to connect to the device locally, meaning that you need to be in the same network. You can find the devices IP address on balenaCloud dashboard as shown in the image below:
In this example, you would connect to:
10.0.55.241:8080 (note that if you are using RealVNC you will need to use double
: to specify a non-standard port).
Deploying your own application
In order to change the application to one of your choice, you need to edit the file
vnc-app/Dockerfile.template and add the application you want to run to the end. For example, changing it to
x11-apps, which installs some x11 sample applications.
RUN install_packages x11vnc \
For this project, we are using supervisor
, a software made to help run and manage multiple applications within one docker container. As soon as the containers initialize, it starts the supervisor
application, which then starts the VNC server and all other applications. The configuration for the default application can be found at
. To change the software from
will be as shown below:
Adding a password to VNC
If you can't trust your network, the first thing you should consider doing is running the VNC Server with a connection password. Luckily adding a password very simple, in balenaCloud dashboard, go to the Device Environment Variables and add a new value with the name
VNC_PASS and value of your password. After adding the password, the VNC container will restart and from now on it will request a password to connect.
Accessing your machine from outside the local network
Being able to only access the application from within your local network may work for your application, but a benefit of balenaCloud is that we can easily set up a way to securely connect to your device over the internet.
For this, you will need to have Balena CLI
version v12.38.5 or newer installed. Keep in mind that this feature is currently experimental, so if you find any inconsistency please let us know! 😉
To get started, copy the UUID (universally unique identifier), as shown image above.
Then head to the terminal and run the command (replacing UUID with the device actual value):
balena tunnel <UUID> -p 8080:8080
The command creates a tunnel connection from the device on port 8080 to your computer localhost on the same port. So now once the tunnel is activated, open VNC Viewer and connect to
localhost:8080, like magic you will be able to control the application remotely 🔮🧙✨.
Done, you are connected!
In this post, we showed how you can run a graphics application on a headless device with the use of a VNC server. We would love to know what GUI programs are you running and hope this project helped you get closer to your goals!
Until next time! ;)