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 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.
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.
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.conf
will be as shown below:
[program:xeyes]
environment=DISPLAY=:1
command=xeyes
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!
Conclusion
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! ;)