mirror of
https://github.com/joleuger/vuinputd.git
synced 2026-07-17 16:36:03 +00:00
Improved README.md for testing NixOS using incus
This commit is contained in:
parent
87694e1a96
commit
2c8d0f9af1
1 changed files with 267 additions and 11 deletions
|
|
@ -1,16 +1,272 @@
|
|||
# Testing vuinputd on NixOS with Incus
|
||||
|
||||
> incus image copy images:nixos/25.11 local: --alias nixos/25.11 --vm
|
||||
> incus launch local:nixos/25.11 nixos-vm --vm
|
||||
> incus stop local:nixos/25.11 nixos-vm
|
||||
> incus config set nixos-vm limits.memory 3GiB
|
||||
> incus config set nixos-vm security.secureboot false
|
||||
> incus start nixos-vm
|
||||
This guide walks through setting up a reproducible NixOS test environment for `vuinputd`
|
||||
using [Incus](https://linuxcontainers.org/incus/), an open-source system container and VM manager.
|
||||
|
||||
> incus exec nixos-vm sed -- -i '/imports = \[/a\ ./vuinputd-test-automation.nix' /etc/nixos/configuration.nix
|
||||
---
|
||||
|
||||
> incus file push vuinputd-test-automation.nix nixos-vm/etc/nixos/vuinputd-test-automation.nix
|
||||
## Complete Script
|
||||
|
||||
> incus exec nixos-vm nixos-rebuild -- switch --max-jobs 1
|
||||
If you are already familiar with Incus and NixOS, here is the full sequence at a glance.
|
||||
The sections below explain each step in detail.
|
||||
|
||||
Execute the test
|
||||
> incus exec nixos-vm bwrap -- --unshare-net --ro-bind / / --tmpfs /tmp --tmpfs /run/udev --dev-bind /run/vuinputd/vuinput/dev-input /dev/input --dev-bind /dev/vuinput /dev/uinput /run/current-system/sw/bin/test-scenarios basic-keyboard
|
||||
```bash
|
||||
# --- Setup ---
|
||||
# Download NixOS VM image (only needed once)
|
||||
incus image copy images:nixos/25.11 local: --alias nixos/25.11 --vm
|
||||
|
||||
# Create and start the VM
|
||||
incus launch local:nixos/25.11 nixos-vm --vm
|
||||
|
||||
# Adjust resources (requires a stop/start cycle)
|
||||
incus stop nixos-vm
|
||||
incus config set nixos-vm limits.memory 3GiB
|
||||
incus config set nixos-vm security.secureboot false
|
||||
incus start nixos-vm
|
||||
|
||||
# --- Configuration ---
|
||||
# Extend the NixOS configuration to include the vuinputd test module
|
||||
incus exec nixos-vm -- sed -i '/imports = \[/a\ ./vuinputd-test-automation.nix' \
|
||||
/etc/nixos/configuration.nix
|
||||
|
||||
# Push the test module into the VM
|
||||
incus file push vuinputd-test-automation.nix nixos-vm/etc/nixos/vuinputd-test-automation.nix
|
||||
|
||||
# Apply the configuration (takes a few minutes on first run)
|
||||
incus exec nixos-vm -- nixos-rebuild switch --max-jobs 1
|
||||
|
||||
# --- Run the test ---
|
||||
incus exec nixos-vm -- bwrap \
|
||||
--unshare-net \
|
||||
--ro-bind / / \
|
||||
--tmpfs /tmp \
|
||||
--tmpfs /run/udev \
|
||||
--dev-bind /run/vuinputd/vuinput/dev-input /dev/input \
|
||||
--dev-bind /dev/vuinput /dev/uinput \
|
||||
/run/current-system/sw/bin/test-scenarios basic-keyboard
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Why Incus?
|
||||
|
||||
Testing `vuinputd` requires a full Linux system stack: a running kernel, udev, `/dev/uinput`,
|
||||
CUSE support, and a container runtime. A plain Docker container or unit test harness is not
|
||||
sufficient because many of these subsystems only exist in a fully booted environment.
|
||||
|
||||
[Incus](https://linuxcontainers.org/incus/) is used here for several reasons:
|
||||
|
||||
- **Full VM support:** Incus can launch proper virtual machines (not just containers), which
|
||||
gives each test environment its own kernel, udev tree, and device namespace — exactly what
|
||||
`vuinputd` needs to operate.
|
||||
- **Clean image lifecycle:** Incus pulls pre-built NixOS images from the
|
||||
[Linux Containers image server](https://images.linuxcontainers.org/), so there is no need
|
||||
to build a NixOS ISO or maintain a local image manually.
|
||||
- **Easy configuration injection:** `incus file push` and `incus exec` allow pushing NixOS
|
||||
configuration files into the VM and triggering a `nixos-rebuild switch` without requiring
|
||||
SSH or manual setup.
|
||||
- **Reproducibility:** Each test run can start from a fresh image, ensuring that leftover
|
||||
state from a previous run does not affect results.
|
||||
- **Isolation from the host:** The VM is fully isolated from the host system, so test runs
|
||||
cannot accidentally interfere with the host's input devices or udev state.
|
||||
|
||||
> **Note:** While `vuinputd` is compatible with other container runtimes such as
|
||||
> `systemd-nspawn`, `Docker`, `LXC`, and `Podman`, Incus VMs are the recommended environment
|
||||
> for automated NixOS testing because they provide a fully booted NixOS system with minimal
|
||||
> setup effort.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- **Incus** installed and initialized on the host (`incus admin init` completed).
|
||||
- The `vuinputd-test-automation.nix` NixOS module available in your working directory.
|
||||
This module configures `vuinputd` and the test tooling inside the VM.
|
||||
- Sufficient disk space for the NixOS VM image (roughly 3–4 GiB).
|
||||
|
||||
---
|
||||
|
||||
## Step-by-Step Guide
|
||||
|
||||
### 1. Download the NixOS VM Image
|
||||
|
||||
```bash
|
||||
incus image copy images:nixos/25.11 local: --alias nixos/25.11 --vm
|
||||
```
|
||||
|
||||
This pulls the NixOS 25.11 image from the public Linux Containers image server and stores it
|
||||
locally under the alias `nixos/25.11`. The `--vm` flag ensures the image is treated as a
|
||||
full virtual machine image rather than a system container rootfs.
|
||||
|
||||
---
|
||||
|
||||
### 2. Launch the VM
|
||||
|
||||
```bash
|
||||
incus launch local:nixos/25.11 nixos-vm --vm
|
||||
```
|
||||
|
||||
This creates and starts a new VM instance named `nixos-vm` from the downloaded image.
|
||||
At this point the VM boots NixOS with its default configuration.
|
||||
|
||||
---
|
||||
|
||||
### 3. Adjust VM Resources
|
||||
|
||||
Stop the VM briefly to apply resource limits before running the NixOS rebuild, which is
|
||||
memory-intensive:
|
||||
|
||||
```bash
|
||||
incus stop nixos-vm
|
||||
incus config set nixos-vm limits.memory 3GiB
|
||||
```
|
||||
|
||||
NixOS system builds (`nixos-rebuild switch`) evaluate a large Nix expression tree and compile
|
||||
Rust code. Without sufficient memory, the build may be killed by the OOM reaper.
|
||||
|
||||
Secure Boot must also be disabled because the NixOS kernel modules required by `vuinputd`
|
||||
(CUSE/FUSE) are not signed for Secure Boot by default:
|
||||
|
||||
```bash
|
||||
incus config set nixos-vm security.secureboot false
|
||||
```
|
||||
|
||||
Then restart the VM:
|
||||
|
||||
```bash
|
||||
incus start nixos-vm
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 4. Inject the Test Configuration
|
||||
|
||||
The NixOS configuration inside the VM needs to be extended to include the `vuinputd` test
|
||||
module. Commands are run inside the VM via `incus exec`. The `--` separator tells Incus where
|
||||
its own arguments end and where the command to execute inside the VM begins — everything after
|
||||
`--` is passed verbatim to the VM shell.
|
||||
|
||||
First, append the import to the existing `configuration.nix`:
|
||||
|
||||
```bash
|
||||
incus exec nixos-vm -- sed -i '/imports = \[/a\ ./vuinputd-test-automation.nix' \
|
||||
/etc/nixos/configuration.nix
|
||||
```
|
||||
|
||||
This uses `sed` to insert `./vuinputd-test-automation.nix` immediately after the `imports = [`
|
||||
line in the NixOS configuration, so NixOS will pick it up during the next rebuild.
|
||||
|
||||
Next, push the test module file into the VM:
|
||||
|
||||
```bash
|
||||
incus file push vuinputd-test-automation.nix nixos-vm/etc/nixos/vuinputd-test-automation.nix
|
||||
```
|
||||
|
||||
The `vuinputd-test-automation.nix` module is responsible for:
|
||||
- Installing and enabling `vuinputd` as a systemd service.
|
||||
- Providing any additional packages needed by the test scenarios (e.g., `bwrap`, `test-scenarios`).
|
||||
- Configuring udev rules for device isolation.
|
||||
|
||||
---
|
||||
|
||||
### 5. Apply the NixOS Configuration
|
||||
|
||||
Trigger a NixOS system rebuild inside the VM:
|
||||
|
||||
```bash
|
||||
incus exec nixos-vm -- nixos-rebuild switch --max-jobs 1
|
||||
```
|
||||
|
||||
The `--max-jobs 1` flag limits parallel build jobs to avoid exhausting VM memory during
|
||||
compilation. This step may take several minutes on first run because Nix will fetch and
|
||||
build all required dependencies.
|
||||
|
||||
After the rebuild completes, the VM is running a fully configured NixOS system with
|
||||
`vuinputd` installed and active.
|
||||
|
||||
---
|
||||
|
||||
### 6. Run the Test Scenarios
|
||||
|
||||
Execute a test scenario inside a restricted sandbox using `bwrap` (Bubblewrap).
|
||||
|
||||
[Bubblewrap](https://github.com/containers/bubblewrap) was chosen as the sandboxing tool for
|
||||
several reasons:
|
||||
|
||||
- **Minimal and universally available:** `bwrap` is a small, single binary with no daemon and
|
||||
no runtime dependencies beyond the kernel. It is packaged in virtually every Linux
|
||||
distribution, so there is no need to install a full container runtime just to run tests.
|
||||
- **Reuses host binaries directly:** Because `bwrap` can bind-mount the host (or VM) filesystem
|
||||
read-only into the sandbox, the test binary and all its dependencies are taken straight from
|
||||
the running NixOS system — no separate rootfs or image needs to be prepared.
|
||||
- **Good proxy for heavier runtimes:** The namespace isolation that `bwrap` provides (mount,
|
||||
network, udev) is the same fundamental mechanism used by Docker, Podman, and systemd-nspawn.
|
||||
If `vuinputd` works correctly inside a `bwrap` sandbox, the same behavior can be expected
|
||||
from more heavyweight container runtimes, making `bwrap` a lightweight but representative
|
||||
stand-in for integration testing.
|
||||
|
||||
|
||||
|
||||
```bash
|
||||
incus exec nixos-vm -- bwrap \
|
||||
--unshare-net \
|
||||
--ro-bind / / \
|
||||
--tmpfs /tmp \
|
||||
--tmpfs /run/udev \
|
||||
--dev-bind /run/vuinputd/vuinput/dev-input /dev/input \
|
||||
--dev-bind /dev/vuinput /dev/uinput \
|
||||
/run/current-system/sw/bin/test-scenarios basic-keyboard
|
||||
```
|
||||
|
||||
#### What this command does
|
||||
|
||||
| Flag | Purpose |
|
||||
|---|---|
|
||||
| `--unshare-net` | Removes network access from the sandbox, ensuring the test is self-contained. |
|
||||
| `--ro-bind / /` | Mounts the entire VM filesystem read-only as the sandbox root. |
|
||||
| `--tmpfs /tmp` | Provides a writable temporary directory. |
|
||||
| `--tmpfs /run/udev` | Provides a writable udev runtime directory, isolating the sandbox from the VM's real udev socket. |
|
||||
| `--dev-bind /run/vuinputd/vuinput/dev-input /dev/input` | Exposes the input devices managed by `vuinputd` (the container-scoped `/dev/input` subtree) at the expected path inside the sandbox. |
|
||||
| `--dev-bind /dev/vuinput /dev/uinput` | Exposes the CUSE-backed virtual `/dev/uinput` device provided by `vuinputd` at the standard `/dev/uinput` path inside the sandbox. |
|
||||
|
||||
This sandbox mimics what a containerized application would see: it has access to the virtual
|
||||
`/dev/uinput` provided by `vuinputd` and the corresponding `/dev/input` event devices, but
|
||||
cannot reach the host's real uinput or other system resources.
|
||||
|
||||
The final argument `basic-keyboard` selects which test scenario to run. Additional scenarios
|
||||
may be available; refer to the `test-scenarios` binary's help output for the full list.
|
||||
|
||||
---
|
||||
|
||||
## Cleaning Up
|
||||
|
||||
To delete the VM and free disk space after testing:
|
||||
|
||||
```bash
|
||||
incus delete --force nixos-vm
|
||||
```
|
||||
|
||||
To also remove the cached image:
|
||||
|
||||
```bash
|
||||
incus image delete nixos/25.11
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If the test fails or `vuinputd` does not appear to be running inside the VM, refer to
|
||||
[docs/DEBUG.md](https://github.com/joleuger/vuinputd/blob/main/docs/DEBUG.md) for debugging
|
||||
strategies applicable to container environments.
|
||||
|
||||
Common issues:
|
||||
|
||||
- **CUSE not available:** Ensure that the `cuse` kernel module is loaded inside the VM
|
||||
(`modprobe cuse`). The test automation module should handle this automatically.
|
||||
- **`nixos-rebuild` runs out of memory:** Increase the memory limit above 3 GiB or reduce
|
||||
parallelism further with `--max-jobs 1 --cores 1`.
|
||||
- **Secure Boot blocking the kernel module:** Verify that `security.secureboot` is set to
|
||||
`false` on the VM instance.
|
||||
- **`/dev/vuinput` not present:** Check that the `vuinputd` systemd service is active
|
||||
(`systemctl status vuinputd`) and that CUSE is loaded.
|
||||
Loading…
Add table
Add a link
Reference in a new issue