Self-sovereign infrastructure platform with secure, encrypted NixOS deployments
This document covers testing Keystone configurations in QEMU/KVM virtual machines, including setup requirements, known issues, and troubleshooting.
Keystone uses libvirt-managed QEMU/KVM VMs for testing NixOS configurations before deploying to physical hardware. This provides a safe, reproducible environment for validating:
libvirtd groupvirtualisation.libvirtd.enable = true;
users.users.<youruser>.extraGroups = [ "libvirtd" ];
Critical: All VM configurations MUST import the qemu-guest.nix profile to function properly.
The qemu-guest.nix profile provides:
Without this profile, you may experience:
In your VM configuration (e.g., vms/test-hyprland/configuration.nix):
{
config,
pkgs,
lib,
modulesPath, # Required for profiles
...
}: {
# Import QEMU guest profile
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
# Ensure complete kernel module set
boot.initrd.availableKernelModules = [
"ahci"
"xhci_pci"
"virtio_pci"
"virtio_blk"
"virtio_net"
"virtio_scsi"
"sr_mod"
];
# Rest of your configuration...
}
The bin/virtual-machine script handles VM lifecycle:
# Create and start VM
./bin/virtual-machine --name keystone-test-vm --start
# Create with custom resources
./bin/virtual-machine --name test --memory 8192 --vcpus 4 --disk-size 50 --start
# Post-installation: snapshot, remove ISO, reboot
./bin/virtual-machine --post-install-reboot keystone-test-vm
# Complete reset
./bin/virtual-machine --reset keystone-test-vm
# Graphical display
remote-viewer $(virsh domdisplay keystone-test-vm)
# Serial console
virsh console keystone-test-vm
# SSH (after installation)
./bin/test-vm-ssh
./bin/test-vm-ssh "systemctl status"
QXL is the working graphics driver for Hyprland in QEMU/KVM VMs:
<graphics type='spice' autoport='yes'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='qxl' ram='65536' vram='65536' vgamem='16384' heads='1'/>
</video>
While QXL is primarily designed for SPICE protocol and has some limitations with Wayland, it provides sufficient DRM/KMS support for Hyprland to function in VM environments.
virtio-gpu without GL acceleration is incompatible with Hyprland:
<video>
<model type='virtio'/>
</video>
Result: ❌ Failed - Missing virgl 3D acceleration, Hyprland cannot initialize EGL
Explanation:
libEGL warning: egl: failed to create dri2 screenQXL vs virtio:
Extensive testing was conducted to enable hardware-accelerated graphics (OpenGL/virgl) for better performance. All hardware acceleration approaches failed due to NVIDIA driver incompatibilities with libvirt.
<graphics type='sdl' display=':0' gl='yes'/>
<video>
<model type='virtio-vga-gl'/>
</video>
Result: ❌ Failed - Attribute syntax incorrect (should be child element)
Error:
The display backend does not have OpenGL support enabled
It can be enabled with '-display BACKEND,gl=on'
<graphics type='sdl' display=':0'>
<gl enable='yes'/>
</graphics>
<video>
<model type='virtio-vga-gl'/>
</video>
Result: ❌ Failed - Same error as above
Analysis: libvirt not properly translating XML to QEMU command-line arguments
<graphics type='spice'>
<listen type='none'/>
<image compression='off'/>
<gl enable='yes' rendernode='/dev/dri/by-path/pci-0000:0a:00.0-render'/>
</graphics>
<video>
<model type='virtio' heads='1' primary='yes'>
<acceleration accel3d='yes'/>
</model>
</video>
Result: ❌ Failed
Error:
qemu-system-x86_64: egl: eglInitialize failed: EGL_NOT_INITIALIZED
qemu-system-x86_64: egl: render node init failed
NixOS Issue #164436: “libvirt: openGL does not work with Nvidia GPUs”
The fundamental problem is an incompatibility between:
qemu:///system modeThis is a known, unresolved issue on NixOS when using NVIDIA GPUs with libvirt OpenGL.
Extensive web research confirmed:
eglInitialize failed errors<gl enable='yes'/>) is correct per libvirt docs (added 2018)If hardware acceleration is unavailable, Hyprland can use software rendering (llvmpipe):
Keep basic virtio graphics (no GL):
<graphics type='spice' autoport='yes'>
<listen type='address' address='127.0.0.1'/>
</graphics>
<video>
<model type='virtio' heads='1' primary='yes'/>
</video>
Add to modules/client/desktop/hyprland.nix or system configuration:
environment.sessionVariables = {
WLR_RENDERER_ALLOW_SOFTWARE = "1";
WLR_NO_HARDWARE_CURSORS = "1";
};
Recommendation: Only use software rendering if hardware acceleration is confirmed unavailable. With proper qemu-guest.nix configuration, basic virtio graphics should work for most testing scenarios.
./bin/build-iso --ssh-key ~/.ssh/id_ed25519.pub
./bin/virtual-machine --name keystone-test-vm --start
# Graphical (for installer)
remote-viewer $(virsh domdisplay keystone-test-vm)
# Serial console (for debugging)
virsh console keystone-test-vm
# From installer or host
nixos-anywhere --flake .#test-hyprland root@192.168.100.99
# Shutdown VM
virsh shutdown keystone-test-vm
# Remove ISO and snapshot
./bin/virtual-machine --post-install-reboot keystone-test-vm
# SSH into VM
./bin/test-vm-ssh
# Inside VM, verify:
bootctl status # Check Secure Boot status
zpool status rpool # Verify ZFS pool
systemctl status hyprland # Check desktop service
Check OVMF firmware:
ls -la /nix/store/*-OVMF-*/FV/
Verify libvirtd:
systemctl status libvirtd
virsh version
lsmod | grep virtio
journalctl -b | grep -i "drm\|egl\|opengl"
Check compositor logs:
journalctl --user -u hyprland
Verify environment variables:
printenv | grep -E "WAYLAND|XDG|WLR"
Test with basic Weston:
# Install weston for testing
nix-shell -p weston
weston --backend=drm-backend.so
Enable in kernel params:
boot.kernelParams = [
"console=ttyS0,115200n8"
"console=tty0"
];
Connect:
virsh console keystone-test-vm
# Press Ctrl+] to exit
-spice port=5900)listen type='none' (local only)Potential areas for enhancement: