looking for a light X11 server for production ready deployment of GUI app.


I found this repository: GitHub - balenablocks/xserver: A simple X11 server block

Is this code production ready? Can I use it as a base of our GUI deployment?
I tested a simple balena push nuc-vm-x64 and I got a blackscreen.

The glxgears doesn’t seem to start.

We were using previously with some hack to start another container with chromium.

FROM balenaplayground/balenalabs-browser:raspberrypi4-64

This all is too hard to maintain with all chromium hack and too heavy app for a raspberrypi, so we are dropping chromium browser and switching to deploy our own GUI Qt5 code.

The previous container model doesn’t work anymore for us. We also miss some x11 knowledge to fix it, and the code base balenaplayground/balenalabs-browser is probably not for production and could break at some point.

If something light and efficient is working as a x11 server, let me know, please.

I also tried: https://github.com/balena-io-examples/x11-window-manager
which worked out of the box on both my vm intel-nuc based and a raspberripy too.

But the codebase is debian stretch which is pretty old, we also had last September outage on such distrib because of ssl lib and letsencrypt root certificated expiration. So I wont recommend to work on outdated debian version.

Also our GUI app is full screen, we may not need a window-manager may be?


1 Like

@Sylvain42 anything that we publish in the balenablocks org is something that we have committed to maintaining. However, that being said, it doesn’t mean that we can guarantee it will work perfectly in every situation and only you can answer the question around if it’s production ready by testing. We’ll always recommend that you test your setup and are completely happy with it before deploying, but if you do find any issues with a block, feel free to submit issues on GitHub and we’ll take a look. By contrast, things in balenaplayground have no commitment at all to maintenance and could be deleted at any time.

cc @nucleardreamer who may be able to give a bit more insight on this block specifically. As I understand it, a fully black screen is to be expected as this is simply a pure X11 implementation, and has no desktop window manager. It should start x and accept connections from clients wanting to render to the screen.

Hi @chrisys

Thanks for your confirm, I’ll dive more in balenablocks/xserver if this one is a maintained project.

I’m supposing that for a full screen GUI app, a window manager is not mandatory. I will see if glxgears can run on it. or another simpler GUI, if any.

I will give you some feedback, here and on the github issue if needed.


More debug on using: balenablocks/xserver as is.

So, the glxgears doesn’t seems to work, out of the box:

git clone https://github.com/balenablocks/xserver balenablocks-xserver
cd balenablocks-xserver
balena push nuc-vm-x64

[Info]      Uploading images
[Success]   Successfully uploaded images
[Info]      Built on x64_01
[Success]   Release successfully created!
[Info]      Release: b4171d5e123a3d838330a677996af914 (id: 2036556)
[Info]      β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
[Info]      β”‚ Service  β”‚ Image Size β”‚ Build Time β”‚
[Info]      β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
[Info]      β”‚ xserver  β”‚ 340.35 MB  β”‚ 25 seconds β”‚
[Info]      β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
[Info]      β”‚ glxgears β”‚ 323.78 MB  β”‚ 18 seconds β”‚
[Info]      β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
[Info]      Build finished in 55 seconds

nuc-vm-x64 device is a Intel-nuc device running as a VM as described in the documentation:

Now, if I analyze the balenablocks/xserver docker-compose.yml

Then I identify the container in the device (trying to match there deployed sha256sum partial id)

Then I do the following to try starting the glxgears container from within balenaOS (1899608_xserver seems to be the corresponding volume: exposed by xserver container) (I’m not a docker-compose.yml expert)

balena ssh
# inside balenaOS I do.
balena run -it -v 1899608_xserver:/tmp/.X11-unix c729f67d1f9c bash

Then I get glxgears working! :fireworks:

So I’m gonna try to understand why the actual glxgears section of the docker-compose.yml don’t do that. It seems it does…
No log available on balenaCloud:


from balenaOS: root@2180851:~# balena logs balena_supervisor

[event]   Event: Service start {"service":{"appId":1899608,"serviceId":1377855,"serviceName":"glxgears","commit":"26cabbd94fe6ad51fd9676f23dffae5a","releaseId":2037953}}
[error]   Scheduling another update attempt in 32000ms due to failure:  Error: Failed to apply state transition steps. (HTTP code 500) server error - error gathering device information while adding custom device "/dev/dri": no such file or directory  Steps:["start"]
[error]         at fn (/usr/src/app/dist/app.js:6:8594)
[error]       at runMicrotasks (<anonymous>)
[error]       at processTicksAndRejections (internal/process/task_queues.js:97:5)
[error]   Device state apply error Error: Failed to apply state transition steps. (HTTP code 500) server error - error gathering device information while adding custom device "/dev/dri": no such file or directory  Steps:["start"]
[error]         at fn (/usr/src/app/dist/app.js:6:8594)
[error]       at runMicrotasks (<anonymous>)
[error]       at processTicksAndRejections (internal/process/task_queues.js:97:5)

"/dev/dri": no such file or directory <==

removed from docker-compose.yml and deployment worked on Intel-nuc VM. :smile:

dri could be related to: Direct Rendering Infrastructure - Wikipedia

Not explored:


Should I open an issue about this on the github balenablocks/xserver?



So after 10h of test and retry in the x11 container world, I finally make it working. :smile: Here is the related docker-compose config sample, very similar from xserver/docker-compose.yaml.

    restart: always
    image: balenablocks/xserver:aarch64-latest
    privileged: true
      UDEV: 1
      io.balena.features.dbus: "1"
      - x11.socket:/tmp/.X11-unix
      - x11.auth:/tmp/.X11-auth
      - src:/src
    network_mode: "none"

    restart: always
    image: out.private.registry/ourgui.app:sometag
      - src:/src
      - x11.socket:/tmp/.X11-unix
      - x11.auth:/tmp/.X11-auth
      - manager

I’m not sure 100% about all parameter here, I didn’t used DRI device and its permission yet, it works without it on a raspberry4 device. I reused the balena’s own image of the xserver container. I guessed the dockerhub path by reading the build-images.sh => FROM balenablocks/xserver:aarch64-latest

So conclusion: it works. Is it production ready? probably not yet, because so much things can break, and it needs huge troubleshooting skills to solve it.

One problem I faced for example: The X server started once on DISPLAY=:3 ==> /tmp/.X11-unix/X3, the GUI client waited forever or was failing continuously trying to reach DISPLAY=:0

Hope this experience can help other user too.

1 Like

Great work and determination @Sylvain42! And, thanks for documenting it for the community, as well. :slight_smile:

This post is super helpful for me, thanks a lot @Sylvain42 for documenting your work on this!

Has anyone else ran into this issue? I’m able to replicate this problem as well, not sure how to address. Any thoughts?

Hi Richard,

The /dev/dri directory contains devices nodes for GPU(s), used for rendering. If this directory doesn’t exist, it would explain your application failing to start. Removing this device mapping may make it work, but only with software rendering, the GPU can’t be used without that device node.

Can you check and see if the /dev/dri directory exists from the host OS?

Hello @jakogut , I experience this issue as well, and I checked whether /dev/dri exists in the xserver container’s ssh, and it doesn’t. I use Balena Fin . Removing the devices: directive from docker-compose.yml made the x11 app container at least try to start, but log says:

Restarting service 'mpd-touch-screen-gui sha256:e9a560828427b5f27fb699a3fe536303643a15a4a8eda241784077f35b29b7ea'
Service exited 'mpd-touch-screen-gui sha256:e9a560828427b5f27fb699a3fe536303643a15a4a8eda241784077f35b29b7ea'