container-safe mediation daemon for /dev/uinput
Find a file
Johannes Leupolz 830fd01ae7 Release v0.2.0
2025-12-06 21:49:54 +00:00
.github/workflows Update rust.yml to include dependencies 2025-11-15 00:12:26 +01:00
cuse-lowlevel Updated documentation for release readiness 2025-10-31 19:58:53 +00:00
debian Release v0.2.0 2025-12-06 21:49:54 +00:00
docs Now we have our own pid 0x5020 under the vendor id 0x1209, which is 2025-12-06 20:40:11 +00:00
uinput-ioctls Updated documentation for release readiness 2025-10-31 19:58:53 +00:00
vuinput-examples Implemented device reuse. This is relevant for Steam. 2025-11-08 22:06:19 +00:00
vuinputd Release v0.2.0 2025-12-06 21:49:54 +00:00
Cargo.toml Include relevant subset of code of libfuse-sys that has not been released by the original maintainer. By this opportunity, also remove the high level api of fuse, because we don't need it. Long term goal would be to migrate to a rust port with less unsafe code. 2025-10-30 23:28:40 +00:00
LICENSE Initial commit 2025-10-24 00:20:54 +02:00
README.md Update DESIGN-document to contain more details. 2025-11-28 22:21:59 +00:00

vuinputd

Run Sunshine and other uinput-based apps inside containers — with full input isolation and zero kernel patches.

A minimal CUSE-based proxy for /dev/uinput that lets unmodified applications (like Sunshine) run inside containers while creating virtual input devices safely on the host.


Overview

Containerizing input-producing software (e.g. Sunshine, Moonlight host replacements, remote desktop servers) improves separation and simplifies deployment.
However, exposing the hosts /dev/uinput directly into a container breaks isolation:

  • Containers can create devices visible system-wide or to other containers.
  • Keyboards and mice may attach to host seats or inject input into active host sessions.

vuinputd exposes a virtual /dev/uinput device inside containers (via CUSE). Input devices created by containerized apps are forwarded to the host kernels uinput subsystem, where they appear as normal /dev/input/event* devices visible to all host applications. Those devices are then injected into the containers with udev announcements.


Architecture

vuinputd solves this by introducing a mediated input stack:

  • A fake /dev/uinput inside each container.
  • A host proxy daemon that safely creates the actual devices via /dev/uinput.
  • The proxy forwards add/remove udev events into the container so that wayland compositors that use libinput and other applications see devices natively.
  • udev rules tag and isolate devices per container, preventing the host from consuming them.

Applications use the /dev/uinput interface unmodified, and the mediation adds negligible overhead.

In principle, this design works with any container runtime — systemd-nspawn, Docker, LXC, Podman, and others.


sequenceDiagram
    box transparent Host
        participant Kernel as uinput (kernel)
        participant Daemon as vuinputd
    end

    box transparent Container
        participant App as Container App
        participant VirtUinput as /dev/uinput (virt)
        Participant Game as Game
    end

    Daemon->>VirtUinput: 1. provides virtual /dev/uinput via CUSE
    App->>VirtUinput: 2. create virtual input device
    VirtUinput-->Daemon: 3. data from virtual /dev/uinput via CUSE
    Daemon->>Kernel: 4. create virtual input device
    Kernel->>Daemon: 5. notify applications on host about new eventX device
    Daemon->>App: 6. notify application in container about new eventX device
    App->>VirtUinput: 7. send input data
    VirtUinput-->Daemon: 8. data from virtual /dev/uinput via CUSE
    Daemon->>Kernel: 9. send input data
    Kernel->>Game: 10. send input data via eventX device

Benefits

  • 🎮 SDL2 & Wayland compatibility: vuinputd ensures compositors and games recognize input devices correctly.
  • 🔒 Strong isolation: Containers see only their own devices; the host sees them but ignores them completely.
  • ♻️ Safe lifecycle: Devices are removed cleanly when the containerized app stops.
  • 🛠️ Simple integration: No kernel patches required — only userspace tools and udev rules.

Documentation

See docs/BUILD.md for a short build and installation guide.
See docs/DESIGN.md for a detailed overview of the architecture, design trade-offs, and security considerations. See docs/USAGE.md for a short usage guide.


🧩 Production Readiness

Current Status: 🚧 Prototype / Alpha — functional, not yet production-grade.

vuinputd is currently in a functional prototype stage. It reliably demonstrates the core concept — exposing /dev/uinput devices inside containers via CUSE — but several aspects require hardening before production use.

Goals for Production Readiness


License

MIT