VNC - No keyboard or mouse with Electron app

I have a docker container running an Electron application (React) together with the Weston compositor.
When enabling VNC and connecting, I can see the display, but cannot interact with either mouse or keyboard. Am I missing something from my docker-compose configuration?

Weston version is 3.2.2
Electron Version: 29.1.4

  • Chromium: 122.0.6261.129
  • Node.js: 20.9.0
  • V8: 12.2.281.22

docker-compose:

services:

  launcher:
    image: xcel-launcher:${LAUNCHER_VERSION}
    container_name: xcel-launcher
    depends_on:
    - weston
    cap_add:
    - CAP_SYS_ADMIN
    - CAP_SYS_TTY_CONFIG
    device_cgroup_rules:
    - c 4:* rmw
    - c 13:* rmw
    - c 199:* rmw
    - c 226:* rmw
    devices:
    - /dev/bus/usb:/dev/bus/usb
    expose:
    - 2228
    - 9229
    - 9223
    - 631
    network_mode: host
    privileged: true
    restart: always
    ulimits:
      nofile:
        hard: 40000
        soft: 20000
      nproc: 65535
    volumes:
    - /tmp:/tmp
    - /dev:/dev
#    - ${USER_HOME}/app:/home/torizon/app # uncomment to run app on host
    - /etc/localtime:/etc/localtime:ro
    - ${USER_HOME}/flex/hosts:/etc/hosts
    - ${USER_HOME}/PDF:/root/PDF
    - ${USER_HOME}/staging:/root/staging
    - ${USER_HOME}/install:/root/install
    - ${USER_HOME}/launcher-config:/root/launcher-config
    - cups:/etc/cups
    - ${USER_HOME}/flex/cupsd.conf:/etc/cups/cupsd.conf
    - /run/dbus:/run/dbus
    profiles: [launcher, ui]

  weston:
    image: weston:${WESTON_VERSION}
    container_name: weston
    cap_add:
      - CAP_SYS_TTY_CONFIG
    device_cgroup_rules:
    - c 4:* rmw
    - c 13:* rmw
    - c 199:* rmw
    - c 226:* rmw
    environment:
      ACCEPT_FSL_EULA: "1"
      ENABLE_VNC: "1"
    network_mode: host
    restart: always
    volumes:
    - /tmp:/tmp
    - /dev:/dev
    - /run/udev:/run/udev
    profiles: [weston, ui]

tdx-info:

Software summary
------------------------------------------------------------
Bootloader:               U-Boot
Kernel version:           5.15.177-6.8.2+git.5a6602cc6c32 #1-TorizonCore SMP PREEMPT Fri Mar 21 16:22:58 UTC 2025
Kernel command line:      root=LABEL=otaroot rootfstype=ext4 quiet logo.nologo vt.global_cursor_default=0 plymouth.ignore-serial-consoles splash fbcon=map:3 ostree=/ostree/boot.1/torizon/c3a7ca8ff2232a05598c6b02529fba8f0dbacced78ea6fbf3ecb16d59a72a05e/0
Distro name:              NAME="TorizonCore"
Distro version:           VERSION_ID=6.8.2-build.30
Distro variant:           VARIANT="Docker"
Hostname:                 verdin-imx8mp-15504086
------------------------------------------------------------

Hardware info
------------------------------------------------------------
HW model:                 Toradex Verdin iMX8M Plus on Verdin Development Board
Toradex version:          0063 V1.1B
Serial number:            15504086
Processor arch:           aarch64
------------------------------------------------------------

Hi, I’m the Toradex AI Assistant.

I might make mistakes. Our support team will step in if needed. If I answered your question, please tick the “Solution” checkbox. For follow-up questions to me, please use @ToradexAI in your post.

Did you like my answer? :+1: :-1:


Hello! Thank you for providing detailed information about your setup.

The issue you’re experiencing—where the VNC session displays your GUI but doesn’t respond to mouse or keyboard input—is almost always due to missing device access permissions in your Weston container. According to the Toradex VNC server setup documentation, one critical device rule is missing from your weston service.

Here’s what you need to update in your docker-compose.yml Weston service:

  1. Add Missing Device Cgroup Rule

    The Weston container must also have access to devices with major number 253 (used for input event handling by Weston). Add the following rule to your device_cgroup_rules:

    device_cgroup_rules:
      - 'c 4:* rmw'
      - 'c 13:* rmw'
      - 'c 199:* rmw'
      - 'c 226:* rmw'
      - 'c 253:* rmw'   # <--- Add this line
    
  2. Ensure All Volume Mounts are Present

    You already have the proper volume mounts, which is great:

    volumes:
      - /tmp:/tmp
      - /dev:/dev
      - /run/udev:/run/udev
    
  3. Use the Official Image (Recommended)

    If possible, consider using the official Toradex Weston image for your module type (e.g., torizon/weston-imx8:$CT_TAG_WESTON) to ensure all dependencies and device access are set up correctly. This is suggested for the best compatibility, especially when using VNC.

Example Weston Section:

weston:
  image: torizon/weston-imx8:$CT_TAG_WESTON
  container_name: weston
  cap_add:
    - CAP_SYS_TTY_CONFIG
  device_cgroup_rules:
    - 'c 4:* rmw'
    - 'c 13:* rmw'
    - 'c 199:* rmw'
    - 'c 226:* rmw'
    - 'c 253:* rmw'
  environment:
    ACCEPT_FSL_EULA: "1"
    ENABLE_VNC: "1"
  network_mode: host
  restart: always
  volumes:
    - /tmp:/tmp
    - /dev:/dev
    - /run/udev:/run/udev

Reference:
Remote Access the TorizonCore GUI using VNC or RDP - Server Setup

Other Important Notes:

  • VNC access is known to reduce GUI responsiveness. The impact depends on your application’s graphics demands.
  • Ensure port 5900 is accessible to your VNC client.
  • VNC is not supported on Torizon 7 at this time.

After making this change, restart your containers. Your VNC session should then accept both mouse and keyboard input.

Let me know if this solves your issue or if you need further assistance!

Best regards, Toradex AI Assistant.

Modifying the docker-compose file and restarting the containers made no difference.
revised docker-compose:

services:
  launcher:
    image: xcel-launcher:${LAUNCHER_VERSION}
    container_name: xcel-launcher
    depends_on:
    - weston
    cap_add:
    - CAP_SYS_ADMIN
    - CAP_SYS_TTY_CONFIG
    device_cgroup_rules:
    - 'c 4:* rmw'
    - 'c 13:* rmw'
    - 'c 199:* rmw'
    - 'c 226:* rmw'
    - 'c 253:* rmw'
    devices:
    - /dev/bus/usb:/dev/bus/usb
    expose:
    - 2228
    - 9229
    - 9223
    - 631
    network_mode: host
    privileged: true
    restart: always
    environment:
      DISPLAY: ":1"
    ulimits:
      nofile:
        hard: 40000
        soft: 20000
      nproc: 65535
    volumes:
    - /tmp:/tmp
    - /dev:/dev
#    - ${USER_HOME}/app:/home/torizon/app # uncomment to run app on host
    - /etc/localtime:/etc/localtime:ro
    - ${USER_HOME}/flex/hosts:/etc/hosts
    - ${USER_HOME}/PDF:/root/PDF
    - ${USER_HOME}/staging:/root/staging
    - ${USER_HOME}/install:/root/install
    - ${USER_HOME}/launcher-config:/root/launcher-config
    - cups:/etc/cups
    - ${USER_HOME}/flex/cupsd.conf:/etc/cups/cupsd.conf
    - /run/dbus:/run/dbus
    profiles: [launcher, ui]

  weston:
    image: torizon/weston-vivante:3.2.2
    container_name: weston
    cap_add:
      - CAP_SYS_TTY_CONFIG
    device_cgroup_rules:
    - 'c 4:* rmw'
    - 'c 13:* rmw'
    - 'c 199:* rmw'
    - 'c 226:* rmw'
    - 'c 253:* rmw'
    environment:
      ACCEPT_FSL_EULA: "1"
      ENABLE_VNC: "1"
      DISPLAY: ":1"
    network_mode: host
    restart: always
    volumes:
    - /tmp:/tmp
    - /dev:/dev
    - /run/udev:/run/udev
    profiles: [weston, ui]

Hi @Steve_S!

I tested the following docker-compose.yaml, and I could both see my mouse and write with the keyboard. Could you please test it and see if it solves the issue?

version: "2.4"
services:
  weston:
    image: torizon/weston-vivante:3
    container_name: weston
    environment:
      - ACCEPT_FSL_EULA=1
      - ENABLE_VNC=1
    network_mode: host
    cap_add:
      - CAP_SYS_TTY_CONFIG
    volumes:
      - /dev:/dev
      - /tmp:/tmp
      - /run/udev/:/run/udev/
    device_cgroup_rules:
      - 'c 4:* rmw'
      - 'c 13:* rmw'
      - 'c 199:* rmw'
      - 'c 226:* rmw'
      - 'c 253:* rmw'
    command: --developer --tty=/dev/tty7
    restart: unless-stopped

Thanks Lucas.
If I stop my launcher container, then yes, I can create a console window and interact with the UI of the Weston container.
I still cannot use mouse or keyboard when the launcher container (Electron App) is running and presenting it’s GUI.

I don’t know if this helps; here is my startup command for the Electron app:
/home/torizon/app/launcher --no-sandbox --enable-features=UseOzonePlatform --ozone-platform=wayland --use-gl=egl --in-process-gpu

Hi @Steve_S!

Just to clarify, did you write the xcel-launcher container, or did you use a pre-existing one?

I suspect that the issue is directly related to the launcher container (possibly a missing parameter), since you can use the mouse and keyboard with only Weston.

Best regards.

Hi Lucas,

I use a torizon/wayland-base-vivante image as my base, onto which I then copy my electron app.
The Dockerfile for the base image is here:

# ARGUMENTS --------------------------------------------------------------------
##
# Board architecture
##
ARG IMAGE_ARCH=${IMAGE_ARCH}
# For armv7 use:
#ARG IMAGE_ARCH=arm

##
# Base container version
##
ARG BASE_VERSION=3.0.8

##
# Application Name
##
ARG APP_EXECUTABLE=single

##
# Debug port
##
ARG SSH_DEBUG_PORT=

##
# Run as
##
ARG SSHUSERNAME=

##
# Board GPU vendor prefix
##
ARG GPU=-vivante

# BUILD ------------------------------------------------------------------------
FROM --platform=linux/${IMAGE_ARCH} torizon/wayland-base${GPU}:${BASE_VERSION} AS Deploy

ARG IMAGE_ARCH
ARG GPU
ARG SSH_DEBUG_PORT
ARG APP_EXECUTABLE
ARG SSHUSERNAME
ENV APP_EXECUTABLE ${APP_EXECUTABLE}

# SSH for remote debug
EXPOSE ${SSH_DEBUG_PORT}
EXPOSE 9229

# Make sure we don't get notifications we can't answer during building.
ENV DEBIAN_FRONTEND="noninteractive"

# stick to bookworm on /etc/apt/sources.list.d
RUN sed -i 's/sid/bookworm/g' /etc/apt/sources.list.d/debian.sources

# for vivante GPU we need some "special" sauce
RUN apt-get -q -y update && \
        if [ "${GPU}" = "-vivante" ]; then \
            apt-get -q -y install imx-gpu-viv-wayland-dev \
        ; else \
            apt-get -q -y install libgl1 \
        ; fi \
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

# your regular RUN statements here
# Install required packages
RUN apt-get -q -y update && \
    apt-get -q -y install \
    openssl \
    openssh-server \
    rsync \
    file \
    curl \
    libatspi2.0-0 \
    libgconf-2-4 \
    libglib2.0-bin \
    libgtk2.0-0 \
    libgtk-3-0 \
    libnotify4 \
    libnss3 \
    libuuid1 \
    libxcb-dri3-0 \
    xdg-utils \
    libxss1 \
    libxtst6 \
    libasound2 \
    smbclient \
    ntpdate \
    fonts-noto fonts-noto-color-emoji fonts-noto-cjk \
    qpdf && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

# CUPS
RUN apt-get -q -y update && \
    apt-get -q -y install \
    usbutils ipp-usb cups cups-filters \
    printer-driver-cups-pdf \ 
    avahi-utils && \
    rm -rf /var/lib/apt/lists/*

#    printer-driver-all \
#    printer-driver-foo2zjs \
#    foomatic-db-compressed-ppds \


# automate for torizonPackages.json
RUN apt-get -q -y update && \
    apt-get -q -y install \
# DO NOT REMOVE THIS LABEL: this is used for VS Code automation
    # __torizon_packages_dev_start__
    # __torizon_packages_dev_end__
# DO NOT REMOVE THIS LABEL: this is used for VS Code automation
    && \
    apt-get clean && apt-get autoremove && \
    rm -rf /var/lib/apt/lists/*

# ⚠️ DEBUG PURPOSES ONLY!!
# copies RSA key to enable SSH login for user
COPY .conf/id_rsa.pub /id_rsa.pub

# create folders needed for the different components
# configures SSH access to the container and sets environment by default
RUN mkdir /var/run/sshd && \
    sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' \
        -i /etc/pam.d/sshd && \
    if test $SSHUSERNAME != root ; \
        then mkdir -p /home/$SSHUSERNAME/.ssh ; \
        else mkdir -p /root/.ssh ; fi && \
    if test $SSHUSERNAME != root ; \
        then cp /id_rsa.pub /home/$SSHUSERNAME/.ssh/authorized_keys ; \
        else cp /id_rsa.pub /root/.ssh/authorized_keys ; fi && \
    echo "PermitUserEnvironment yes" >> /etc/ssh/sshd_config && \
    echo "Port ${SSH_DEBUG_PORT}" >> /etc/ssh/sshd_config && \
    su -c "env" $SSHUSERNAME > /etc/environment

RUN rm -r /etc/ssh/ssh*key && \
    dpkg-reconfigure openssh-server

RUN echo "torizon:Pa55w0rd" | chpasswd

RUN usermod -aG sudo torizon
RUN usermod -aG lpadmin torizon

CMD [ "/usr/bin/bash", "/usr/src/prodstart.sh" ]

And then on top of that:

ARG base

FROM $base

# BUILD ------------------------------------------------------------------------
FROM --platform=linux/arm64 ${base} AS Deploy

# nc required for 'pinging' printers
RUN apt-get -q -y update && \
    apt-get -q -y install \
    netcat-traditional && \
    rm -rf /var/lib/apt/lists/*

# copy the build
COPY host-scripts /home/torizon/app/host-scripts
COPY prodstart.sh /usr/src/prodstart.sh
COPY out/launcher-linux-arm64 /home/torizon/app

WORKDIR /home/torizon/app

Hi @Steve_S,

Apologies for the delayed response.

From what I can see, the issue appears to be related to Electron, which falls more on the application side. Since we’re not experts in Electron, I’d recommend checking our Partner Network, where you can find partners with the right expertise to support you and help move your project forward. You may also find it helpful to search on Electron forums, as they’re a good place to get guidance from developers familiar with similar issues.

Best regards.