Files
vuinputd/docs/USAGE.md
2025-11-05 21:39:14 +00:00

6.7 KiB
Raw Blame History

Usage Guide

This guide explains how to run applications that use /dev/uinput (like Sunshine) inside containers using vuinputd. Youll learn how to connect your container to the hosts input proxy, configure permissions, and verify that input devices are visible and functional inside the container.


1. Overview

vuinputd allows unmodified apps that use /dev/uinput to run safely inside containers. It provides each container with a virtual /dev/uinput, while a host-side daemon mediates all access to the real uinput subsystem.

This guide shows how to:

  1. Run a container (Docker, systemd-nspawn, or LXC/LXD)
  2. Connect it to the hosts virtual /dev/uinput
  3. Verify that device creation and input forwarding work correctly

2. Prerequisites

Before continuing, ensure the following:

  • vuinputd is installed and running on the host → see docs/BUILD.md

  • You have root access on the host (required for mounting and device permissions)

  • The host kernel supports:

    • /dev/uinput
    • FUSE/CUSE
  • Optional tools for debugging and validation inside the container:

    apt-get install libinput-tools evtest udev tmux
    

3. Quick Start (Docker Example)

This is the simplest way to verify that vuinputd works.

🖥️ On the Host

  1. Install Docker:

    sudo apt-get install docker.io
    
  2. Start a test container with vuinputds virtual device mapped in:

    sudo docker run -it \
        --name vuinput-test \
        --device=/dev/vuinput:/dev/uinput \
        --device-cgroup-rule='c 13:* rw' \
        --mount type=bind,src=<path-to-vuinputd-build>,dst=/build \
        ubuntu:noble
    

    (Replace <path-to-vuinputd-build> with your actual build directory)

  3. Test the application

Just run those lines in the container.

# Allow access for any application
chmod 666 /dev/uinput
# Prepare udev stubs so applications relying on libudev work
mkdir -p /run/udev/data/
touch /run/udev/control
# Run the demo application
/build/release/mouse-advanced

The vuinputd daemon on the host should provide some logs. The following section "Verifying Operation" describes a more elaborate check and also some screenshots.

  1. Optional: To reuse the container later:

    sudo docker start -ia vuinput-test
    
  2. To clean up:

    sudo docker rm vuinput-test
    

4. Runtime-Specific Setup

🐳 Docker

(As shown above in Quick Start.)

Key flags:

  • --device=/dev/vuinput:/dev/uinput — mounts the fake uinput device
  • --device-cgroup-rule='c 13:* rw' — allows access to input devices
  • Optional: bind your build directory to /build for testing binaries

🧱 systemd-nspawn

  1. Install mkosi:

    sudo apt-get install mkosi
    
  2. Create an Ubuntu 24.04 image:

    mkosi -d ubuntu -r noble -t directory ubuntu-dir
    
  3. Launch a container with vuinputd bound:

    /usr/bin/systemd-nspawn \
        -M vuinputtest \
        -D ubuntu-dir \
        --network-veth \
        --system-call-filter="@keyring bpf" \
        --bind=/proc:/run/proc \
        --bind=/sys:/run/sys \
        --bind=/dev/vuinput:/dev/uinput \
        --bind=/dev/dri \
        --property="DeviceAllow=char-drm rw" \
        --property="DeviceAllow=char-input rw" \
        --property="DeviceAllow=/dev/vuinput rw" \
        -b
    

🪶 LXC / LXD

Add the following to your container configuration:

lxc.cgroup2.devices.allow: c 120:414795 rwm
lxc.mount.entry: /dev/vuinput dev/uinput none bind,optional,create=file

Then restart the container.

(Adjust the major/minor numbers to match /dev/vuinput on your host — check with ls -l /dev/vuinput. In the current release, 120:414795 is hardcoded. This may change in the future.)


5. Inside the Container

Once inside the container shell:

chmod 666 /dev/uinput
apt-get update

# Optional: install test tools
apt-get install libinput-tools udev evtest tmux

# Prepare udev stubs
mkdir -p /run/udev/data/
touch /run/udev/control

6. Verifying Operation

To test everything, use multiple tmux windows for parallel monitoring.

  1. Start libinput event monitor:

    libinput debug-events
    
  2. In another window, observe udev events:

    udevadm monitor -p
    
  3. In a third, run:

    evtest /dev/input/event*
    
  4. Finally, run the demo binary:

    /build/release/mouse-advanced
    

Expected Results

You should see:

  • libinput reporting device creation and input events
  • udevadm announcing a new /dev/input/event*
  • evtest showing input data (e.g. mouse movement)
  • journalctl on the host showing vuinputd logs about device creation and event forwarding

Sample output from libinput debug-events:

Sample output from udevadm monitor -p:

Sample output from mouse-advanced:

Sample output from evtest:

Sample output from journalctl showing vuinputd output:


7. Troubleshooting

Symptom Possible Cause Fix
/dev/uinput not found vuinputd not running Start vuinputd on host
Permission denied Missing chmod or wrong cgroup rule Run chmod 666 /dev/uinput or adjust device rule
No events in container Missing /run/udev/control Create dummy udev files (see section 5)
Device appears on host seat udev rules not isolating Add udev rules from vuinputd/udev-folder
Input delayed or missing CUSE layer error Check host logs via journalctl -u vuinputd

8. Notes and Advanced Topics

  • You can safely run multiple containers.

  • Devices are automatically cleaned up when the container stops.

  • Works with Wayland and X11 compositors using libinput.

  • For deeper details, see:


9. References