This project runs a headless Labwc Wayland session inside a Docker container, primarily designed for remote access via Sunshine and WayVNC. It features isolated input device handling (thanks to this post from the Wolf project), allowing passthrough of keyboards, mice, touchscreens, and gamepads, along with custom gesture recognition (lisgd) and button remapping (Makima).
- Labwc: Lightweight Wayland compositor based on wlroots.
- Sunshine: Self-hosted, low-latency game stream host compatible with Moonlight clients.
- WayVNC: VNC server for Wayland compositors.
- Pipewire: Modern audio server for handling audio within the container.
- Fake Udev (
start-fake-udev.sh): Custom script that monitors host udev events for specific input devices and simulates their addition/removal within the container usingmknodandfake-udevfrom the Wolf project. This provides input device isolation. lisgd: Touchscreen gesture daemon. Integrated withstart-fake-udev.shto start/stop automatically when a "Touch passthrough" device is detected/removed. Gestures are configured directly withinstart-fake-udev.sh.- Default Gestures (Configured in
start-fake-udev.sh):- 3-finger swipe UP: Launch
kittyterminal. - 3-finger swipe DOWN: Launch
rofiapplication launcher (with D-PAD navigation).
- 3-finger swipe UP: Launch
- Default Gestures (Configured in
makima: Input device remapper daemon. Used here primarily to remap gamepad D-PAD inputs to keyboard arrow keys, enabling gamepad navigation in applications like Rofi. Configuration is per-device.- Rofi Wrapper (
rofi-makima.sh): A script designed to launchmakimaonly when Rofi is active and kill it when Rofi closes. This works aroundmakima's lack of application-specific binding support under Labwc. - Configuration via Volumes: Most application configurations are mounted from the host, allowing easy customization without rebuilding the container.
- Docker & Docker Compose: Ensure Docker and Docker Compose (or
docker compose) are installed on the host system. - Host User Permissions: The user running Docker needs appropriate permissions to manage Docker.
inputGroup: The host user should ideally be part of theinputgroup to allow monitoring udev events (though the script runs as root inside the container, access might still be relevant depending on host setup). The container explicitly adds theappuserto group GID104(a commoninputGID) - verify this GID matches theinputgroup GID on your host (getent group input | cut -d: -f3) and adjust thegroup_addsection indocker-compose.ymlif necessary.- Kernel Modules: Ensure the
uinputkernel module is loaded on the host (sudo modprobe uinput). You might need to configure it to load automatically on boot. - Graphics Drivers: Appropriate host graphics drivers (e.g., NVIDIA, AMD, Intel) are required for GPU acceleration within the container (passed via
/dev/dri).
This project uses configuration files mounted from the host into the container. Key configuration directories within this repository are:
config/labwc/: Labwc configuration (rc.xml,autostart,themerc, etc.).config/sunshine/: Sunshine configuration files.config/makima/: Makima device remapping configuration files.- Files must be named exactly after the device name reported by
evtestorlibinput list-devices(e.g.,Sunshine X-Box One (virtual) pad.toml). - Place your
.tomlfiles here; they will be mounted to/home/appuser/.config/makimainside the container.
- Files must be named exactly after the device name reported by
config/sfwbar/: Configuration for sfwbar (if used).config/wireplumber/: Pipewire session manager configuration.executables/: Contains helper scripts.start-fake-udev.sh: Manages device simulation and starts/stopslisgd. Gesture commands are configured here.rofi-makima.sh: Wrapper script to runmakimaalongside Rofi. Note: This script usessudointernally and requires theappuser(UID 1000) inside the container to have passwordlesssudopermissions formakimaandkill, or the script needs modification. You also need to ensure this script is placed in a location accessible within the container's$PATHor called via its full path. The Labwcrc.xmlandstart-fake-udev.shshould be updated to call this script instead ofrofidirectly if you want the conditionalmakimabehavior.
Modify the files in these directories on the host to customize the container's behavior.
To build the Docker image:
docker compose build
# or
docker-compose buildTo start the container in detached mode:
docker compose up -d
# or
docker-compose up -d- Sunshine: Access the Sunshine web UI (usually
https://<host-ip>:47990) to pair clients (like Moonlight). Streaming occurs over the other configured ports. - WayVNC: Connect using a VNC client to
<host-ip>:5900.
The container uses a multi-layered approach for input devices passed through from the host:
start-fake-udev.sh: Runs inside the container with elevated privileges. It monitors hostudevadmevents for specific device names (configured in the script). When a target device is added/removed on the host, this script creates/removes the corresponding/dev/input/event*node inside the container usingmknodand sends a simulated udev event using thefake-udevutility. This makes the container's system (and compositors like Labwc) aware of the device.lisgd: This script also starts/stopslisgdwhen a "Touch passthrough" device is added/removed, binding gestures defined within the script itself.makima: This daemon reads device events directly. It's configured via.tomlfiles named after specific devices. It can remap buttons/keys. In this setup, it's used to map gamepad D-PAD events to keyboard arrow keys. It can be run constantly as a service or conditionally using therofi-makima.shwrapper.
- Logs: Check container logs for errors:
docker compose logs -f labwc-sunshine(ordocker-compose ...). - Permissions: Ensure correct host user permissions (Docker group) and that the
inputgroup GID indocker-compose.ymlmatches the host. Check/dev/dri,/dev/uinput,/dev/uhidpermissions on the host. - Device Names: Verify the device names in
start-fake-udev.shand the filenames inconfig/makima/match the actual device names reported byevtestorlibinput list-deviceson the host. rofi-makima.shSudo: If using the wrapper script, ensure theappuser(UID 1000) inside the container has the necessary passwordlesssudorights configured, or modify the script to avoidsudoifmakimacan run without it (depends on group memberships and device permissions).