Running a GUI application with balenaCloud

Running a GUI application with balenaCloud

Running a GUI application with balenaCloud

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 next step is to download the code for this project from GitHub. Go to: and download the project as shown in the image below:

Running a GUI application with balenaCloud

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 🦄:

Running a GUI application with balenaCloud

Go back to the dashboard and you’ll be able to see the status of your device downloading and installing everything.

Running a GUI application with balenaCloud

If everything is up and running correctly, you will be able to see a log message saying that gnome-calculator and x11vnc are both running. Good job, now let’s go ahead and try to connect to the device and use the calculator.

Running a GUI application with balenaCloud

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:

Running a GUI application with balenaCloud

In this example, you would connect to: (note that if you are using RealVNC you will need to use double : to specify a non-standard port).

Running a GUI application with balenaCloud

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.

FROM balenalib/%%BALENA_MACHINE_NAME%%-debian:stretch-run RUN install_packages x11vnc \ x11-utils \ xvfb \ wmctrl \ supervisor \ x11-apps ...

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 vnc-app/supervisor/app.conf. To change the software from gnome-calculator to xeyes, the app.confwill be as shown below:

environment=DISPLAY=:1 command=xeyes 

Running a GUI application with balenaCloud

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.

Running a GUI application with balenaCloud

Running a GUI application with balenaCloud

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 v9.12.0 or newer installed. Keep in mind that this feature is currently experimental, so if you find any inconsistency please let us know! 😉

Running a GUI application with balenaCloud

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!

Running a GUI application with balenaCloud


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!

If you have any questions or suggestions about this post, let us know in our forums at, on Twitter @balena_io, on Instagram @balena_io or on Facebook.

Until next time! 😉