Move Qt platform theme setup (plasma-integration, breeze, breeze-gtk,
breeze-icons) into the base VM configuration so all guests get consistent
theming out of the box. Previously qt.platformTheme was set in
optionalGuestSettings but qt.enable was never set, so it had no effect.
optionalGuestSettings now only configures dark theme (BreezeDark color
scheme, Breeze-Dark GTK theme, breeze-dark icons) on top of the base.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
xdg-desktop-portal-kde reports color-scheme via org.freedesktop.appearance
by reading QApplication palette colors. Without a KDE dark color scheme in
kdeglobals, the portal reported "prefer-light", overriding the GTK dark
theme settings for Firefox and other apps.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The idle watchdog used `systemctl --user --machine=user@.host` which
internally spawns systemd-stdio-bridge requiring PAM session setup.
A broken pam_lastlog2.so caused this to fail every 5 seconds, spamming
the journal. Worse, the failed query returned empty output (ACTIVE=0),
so the watchdog never detected running commands and shut down VMs
prematurely based on idle time alone.
Fix by connecting to the user D-Bus socket directly (root can access it)
and adding pipefail + || continue so query failures skip the cycle.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When a VM is not running, its TAP interface has no carrier, so networkd
refuses to assign static addresses (hostAddress) and the link gets stuck
in "configuring" state. This causes systemd-networkd-wait-online to block
for 2 minutes. Setting ConfigureWithoutCarrier=yes lets networkd assign
addresses immediately regardless of carrier state.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
qcow2 causes O_DIRECT failures on ext4 due to crosvm doing unaligned
access when parsing the qcow2 header. Since we don't use any qcow2
features (the disk is created fresh and deleted on stop), a raw sparse
file via truncate works just as well and also removes the qemu package
dependency from the VM service.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The previous --ignore approach (6a28576) didn't prevent the timeout
because bridges stayed in "configuring" setup state waiting for IPv6
autoconfiguration that never arrives. Set RequiredForOnline=no,
IPv6AcceptRA=no and LinkLocalAddressing=no directly in the networkd
.network units for all vmsilo TAP and bridge interfaces.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prevents systemd-networkd-wait-online.service from timing out when
vmsilo TAP/bridge interfaces are not up (VMs not running), which
was causing long delays during nixos-rebuild switch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Emit the resolved VM color as an X-VmSilo-Color attribute in all
generated .desktop and .directory files, for kicker to draw colored
icon borders in the application menu.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Remove unused ifIndexToIfName and sanitizeName from helpers.nix
- Deduplicate normalizeBdfLocal in extractBdf (reuse module-level normalizeBdf)
- Remove unused sharedHomePath variable in scripts.nix
- Fix "Packate" typo in overlay.nix comment
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Route VM traffic through the host directly instead of requiring a
separate netvm VM. Uses the same nftables NAT and forward firewall
rules as VM-based netvms, applied on the host using TAP interface
names. Removes the hostNetworking.nat options in favor of the
unified netvm approach.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
VMs with network.netvm now automatically pull in their netvm via
Wants=, ensuring the netvm starts when the client VM is started.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Under networkd, networking.bridges only generates .netdev and member
.network files but not a .network file for the bridge device itself.
Without a matching .network unit, networkd won't bring the bridge link
up. Add empty networking.interfaces entries for each bridge so networkd
manages them.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds network.netvm / network.isNetvm options that auto-configure
point-to-point VM networking (host bridge, TAP interfaces, guest IPs,
default routes, masquerade NAT, and forward firewall rules) without
manual interface configuration.
New options:
programs.vmsilo.netvmRange — IP pool for /31 auto-allocation (default 10.200.0.0/16)
vm.network.isNetvm — mark VM as a network gateway
vm.network.netvm — route this VM through a named netvm
vm.network.netvmSubnet — override auto-allocated /31 (pin specific address)
Architecture:
modules/netvm.nix computes all (netvm, client) pairs and writes to
_internal.netvmInjections to avoid infinite recursion in the module
system. networking.nix, scripts.nix, and services.nix each have a
getEffectiveInterfaces helper that merges user-configured and
injected interfaces transparently.
Guest nftables config (masquerade NAT, forward isolation between
clients, ip_forward sysctl) is injected via _generatedGuestConfig
and merged into the rootfs build in scripts.nix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
When a bridge is added to the config and nixos-rebuild switch is run,
the per-bridge netdev service is not started automatically because
network-setup.service is already active (RemainAfterExit). Add Wants
and After dependencies on <bridge>-netdev.service for each bridge used
by a VM's TAP interfaces so systemd starts it on demand when the VM
service starts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add assertion to check user-specified tap.name overrides against Linux
IFNAMSIZ constraints (max 15 chars, letter start, alphanumeric/hyphen/
underscore). Previously only guest-visible interface names were validated;
invalid tap.name values would only surface as runtime kernel errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Work around an annoying issue with the Intel AX210. It has a hardware bug
where the PCIe link will go into L1 before initialisation is complete. The
driver works around this by spamming read calls to an MSI-X register to keep
the link alive until firmware is ready. But these register accesses are
trapped by crosvm, and that's not fast enough.
As a shitty workaround, add an option to hide device MSI-X capability from
the VM. It should fall back to MSI. I hope.
The vsock-cmd socket was wantedBy sockets.target, causing it to listen
on vsock:5000 as soon as the user manager started — before wayland,
dbus, and pipewire were ready. Commands arriving during this window
would fail. This also caused root's user manager to try binding the
same port ("Address already in use").
Tie the socket to graphical-session.target so it only listens once the
session environment is fully set up. The host proxy's existing retry
loop handles the brief delay.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
GPU VMs need a Wayland socket, so starting them at multi-user.target
(boot) fails. The session-bind user service now also starts autoStart
GPU VMs when the graphical session begins. Non-GPU VMs still start at
boot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The guest-side ifname regex rejected `-`, which is a legal character for
Linux interface names. Also add a NixOS assertion so invalid names are
caught at config evaluation rather than silently skipped at guest boot.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add libvulkan.so to crosvm LD_LIBRARY_PATH. Along with the earlier fix
commits, this now enables full guest-side vulkan (tested with vkcube
and vulkaninfo - they're using the host GPU). Huzzah!
Was hoping enabling vulkan and not opengl would make mesa fall back to
zink, so we could skip virgl2 and just translate opengl to vulkan. But
it still ends up using llvmpipe. Forcing zink gives errors, getting that
working will be the next goal.
Replace the low-level gpu attrset (mapped directly to --gpu args) with a
submodule of supported features: wayland (cross-domain), opengl (virgl2),
and vulkan (venus). Vulkan automatically adds --gpu-render-server.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Use fixed string "ephemeral" instead of deriving from VM name, since
disk IDs only need to be unique within a single VM's block devices.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
virtiofsd fails if the shared home directory doesn't exist yet. The
createSharedHome script was running as ExecStartPre on the crosvm VM
service, but virtiofsd starts before the VM service. Move it to the
virtiofsd-home unit so the directory is created before virtiofsd needs it.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Nvidia GPU drivers require RWX memory pages, which crosvm's seccomp
sandbox blocks. This option switches to a crosvm-nvidia build with
a relaxed W+X memory policy, keeping the default secure.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
We're already starting a dbus normally, the wrapped dbus-launch is
not needed. Passing a command also prevents sommelier from working.
Also update sommelier since the old version was broken for virtio-gpu.
Breaks the monolithic rootfs-nixos/configuration.nix (582 lines) into
7 files under rootfs-nixos/guest/ for better readability and separation
of concerns: boot, users, networking, wayland, command, system, plus a
shared kernel-param-helper.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>