Commit graph

102 commits

Author SHA1 Message Date
faad5006c9 cleanup: remove vmsilo-start-* scripts, rename vmsilo-usb to vm-usb, fix vm-run output
- Remove vmsilo-start-* user-facing symlinks from package.nix (internal
  VM launcher scripts are only used by systemd ExecStart, not by users)
- Rename vmsilo-usb to vm-usb to match the vm-* naming convention
- Increase socat -t timeout in vm-run from default 0.5s to 5s to fix
  missing output from console commands (cloud-hypervisor proxy startup
  latency exceeded the default timeout window)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:51:57 +00:00
08709827fb feat: replace crosvm USB passthrough with usbip-over-vsock
Replace crosvm xhci-based USB passthrough with usbip-rs over vsock,
enabling USB passthrough for both crosvm and cloud-hypervisor VMs.

Guest runs a persistent usbip-rs client listener on vsock port 5002.
Host runs one sandboxed usbip-rs host connect process per attached
device as a systemd template service (vmsilo-<vm>-usb@<devpath>).

Eliminates the JSON state file, file locking, and crosvm-specific
shell helper library in favor of systemd as the source of truth.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-22 16:15:27 +00:00
99cccf89ba VM option cloudHypervisor -> cloud-hypervisor for consistency 2026-03-22 09:55:43 +00:00
43438277d8 fix: use screen -dmS with Type=forking for console drain service
screen -dmS forks to background (daemon mode), which should work
without a controlling terminal. Type=forking tells systemd to expect
the fork.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 20:10:06 +00:00
dae577fe0f fix: switch from screen to tmux for console drain sessions
screen requires a controlling terminal which systemd services don't
provide. tmux works without a terminal via new-session without -d.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 20:04:27 +00:00
cb4c7d163e docs: update vm-shell detach instructions for screen
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 19:49:11 +00:00
cd73430c3e feat: add RUST_BACKTRACE=full to all Rust services and sound.logLevel option
Set RUST_BACKTRACE=full on VM, GPU, sound, dbus-proxy, balloond, and
wayland-seccontext services for better crash diagnostics. Add per-VM
sound.logLevel option (default "info") that sets RUST_LOG on the
vhost-device-sound service.

Also document previously undocumented options in README: cloud-hypervisor
hugepages, netvmRange, sound.logLevel, sound.seccompPolicy,
cloudHypervisor.hugepages, cloudHypervisor.seccompPolicy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:53:49 +00:00
ce22c095cb feat: add gpu.disableSandbox option for debugging GPU service
Allows disabling non-seccomp sandboxing (filesystem isolation, device
allow, capabilities, private network, etc.) per VM. Seccomp remains
independently controlled via gpu.seccompPolicy.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:00:04 +00:00
57a71e16ae feat: add per-VM tray.enable option (default false)
Tray proxy was unconditionally enabled for all crosvm VMs. Add
tray.enable so it must be opted into per VM. When disabled, neither
the host-side tray service nor the guest-side tray daemon are created.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:37:32 +00:00
5d587eb421 docs: update README for GPU sub-options, remove stale vulkan references
Remove vulkan/venus references (option was removed in cloud-hypervisor
refactor) and document gpu.allowWX, gpu.logLevel, gpu.seccompPolicy
per-VM options that were missing from the options table and GPU section.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 09:36:45 +00:00
cf16f2b07c docs: update README for cloud-hypervisor options, remove vm-start-debug
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-21 09:36:22 +00:00
62ceb91b90 Update docs for vmsilo-dbus-proxy rename and notification support
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 17:21:39 +00:00
7e2f3cf708 Document automatic DNS configuration for netvm setups
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 14:31:37 +00:00
6fd44b9d2f Change default shared home path from /shared/<vm> to /shared/<vm>/home
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:20:14 +00:00
dfa2dd8054 Add sharedDirectories mountPath option for automatic guest mounts
Adds a `mountPath` option to `sharedDirectories.<name>` that, when set,
automatically mounts the virtiofs share at the specified path inside the
guest via systemd.mount-extra kernel parameter. The implicit sharedHome
entry now uses this same code path (mountPath = "/home/user") instead of
a hardcoded special case.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 11:16:49 +00:00
463f73d274 Add PAM limits for guest PipeWire realtime scheduling
xdg-desktop-portal 1.20.3's Realtime portal intercepts PipeWire's RT
scheduling requests but fails silently: it calls fstatat(pidfd, "ns/pid")
to check the caller's PID namespace, which returns ENOTDIR because pidfds
don't support being used as directory FDs on current kernels (6.18/6.19).
PipeWire uses fire-and-forget D-Bus and never sees the error.

Fix by granting the @audio group PAM limits (rtprio=95, nice=-19,
memlock=unlimited) so PipeWire's module-rt can call sched_setscheduler
directly, bypassing both the broken portal and rtkit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:35:15 +00:00
b876265793 Reduce default core isolation from "full" to "vm"
Full isolation has too much impact to be a default. Even on an almost
unloaded machine with a couple of VMs running it results in audio buffer
underruns due to the significant scheduling latency.

This change is fine because with vmsilo, the trust domain is the VM. There
isn't much reason to protect apps from other apps running in the same VM.
Better to run those apps in separate VMs in that case.
2026-03-18 11:35:10 +00:00
eda15f16f8 Update options and docs for vhost-device-sound
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 18:45:22 +00:00
43c99ec162 Document USB device passthrough in README and CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 13:10:54 +00:00
0a07f7f14e Switch ephemeral overlay from qcow2 to raw sparse image
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>
2026-03-08 00:49:44 +00:00
3b0bbd088d Update docs and examples 2026-03-07 17:49:04 +00:00
3b640b1662 netvm: support network.netvm = "host" for host-routed networking
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>
2026-03-07 15:28:47 +00:00
f33abeace0 Update README.md and examples to use netvm config 2026-03-07 15:07:04 +00:00
bb1ab85237 netvm: add network.netvm/isNetvm convenience layer for auto VM-to-VM links
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>
2026-03-07 14:21:38 +00:00
85c88cfb33 Change nixosVms from list to attrset keyed by VM name
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 20:26:55 +00:00
b247b46066 Start autoStart GPU VMs with session instead of at boot
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>
2026-02-25 22:14:53 +00:00
f34b494dd1 Fix last blocker for guest-side vulkan
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.
2026-02-22 16:16:25 +00:00
f1041db662 Refactor GPU option from raw crosvm attrset to high-level feature config
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>
2026-02-22 13:06:41 +00:00
16b08cc3c8 Add nvidiaWeakenSandbox option to select crosvm-nvidia package
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>
2026-02-21 00:46:58 +00:00
a20c5d06af Use darkred as default VM color
Plain red is distractingly intense.
2026-02-20 18:29:08 +00:00
8de5e55801 Replace sound tri-state with playback/capture booleans
Instead of passing raw crosvm attrsets, sound is now configured
with two booleans: sound.playback (default true) and sound.capture
(default false, implies playback).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 00:30:39 +00:00
c2e054171b Replace crosvm built-in virtiofs with virtiofsd
Switch shared directories from crosvm's built-in --shared-dir to
external virtiofsd processes connected via --vhost-user. Each shared
directory gets a dedicated virtiofsd systemd service that starts
before the VM and stops when the VM stops.

The sharedDirectories option is now an attrsOf submodule (keyed by
fs tag) with typed options for all virtiofsd flags instead of the
previous freeform list passed directly to crosvm.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 23:57:10 +00:00
67b8284c9c Add schedulerIsolation option to configure hyperthreading mitigations
Also add crosvm options to hint to the scheduler to put it on the performance
cores, enable vCPU stop on guest suspend and disable some legacy peripheral
emulation.
2026-02-19 22:00:01 +00:00
4238d34638 Update kwin clipboard patches for separate global clipboard
Instead of using host buffer, use a global vmsilo buffer. Host buffer is
treated just like VM buffers - copying to/from it needs explicit action. This
is more like the Qubes behavior, only difference is that copy/paste to/from
the host clipboard is allowed.
2026-02-19 21:58:50 +00:00
cd1fc27a4a Add sound capture support, bump crosvm and wayland proxy 2026-02-19 00:53:27 +00:00
be6a175c87 README.md: Update quickstart config, minor updates 2026-02-18 23:19:34 +00:00
2880cbcdc4 balloond: tune defaults: critical floor 256m, bias 400m
Now that critical_guest_available is a hard floor, lower it from 400m
to 256m (guests can safely operate with 256 MiB free). Increase
guest_available_bias from 300m to 400m for stronger graduated
resistance as the balloon fills, keeping the comfortable equilibrium
point around 656 MiB.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:31:13 +00:00
4791e391f0 balloond: enforce critical_guest_available as hard floor and add CLI arg
The critical_guest_available threshold was not actually a floor —
when both host and guest were below their critical thresholds, the
clamp bounds inverted and were skipped entirely, letting the
equalization formula push guests to dangerously low memory (34 MiB
observed with a 400 MiB "critical" threshold).

Add a hard floor: after computing the balloon delta, clamp positive
deltas so inflation never pushes guest free memory below
critical_guest_available, regardless of host pressure.

Also add --critical-guest-available CLI arg (default 400m) and the
corresponding NixOS option (criticalGuestAvailable) so both knobs
are tunable. To target e.g. 300 MiB as a floor:

  --critical-guest-available 250m --guest-available-bias 50m

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:29:03 +00:00
e52d79706a docs: document PSI-adaptive polling options
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 19:21:10 +00:00
31984c995a README.md: Update rootfs size estimate (erofs is much smaller) 2026-02-18 18:54:40 +00:00
e6e14e0d33 Add per-VM copyChannel option to include NixOS channel in rootfs
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:47:05 +00:00
be71982c7d Replace ext4+qcow2 rootfs with erofs
The rootfs is read-only, used only as an overlayfs lower layer — ext4
with journaling was a poor fit. erofs is purpose-built for this: compressed
(lz4hc), compact metadata, faster random reads.

The new builder (make-erofs-image.nix) runs nixos-install and mkfs.erofs
under a single fakeroot session, eliminating the QEMU VM previously needed
during the build.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 18:21:33 +00:00
9bf6f510bd Stop GPU-enabled VMs on desktop session end
GPU VMs connect to the host Wayland socket, which is destroyed on logout.
Add per-VM systemd user services that bind to graphical-session.target and
stop the VM system service when the session deactivates. Also make
--wayland-security-context conditional on GPU being enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 17:55:07 +00:00
af137e9594 Add explicit color assignment to doc examples 2026-02-18 16:40:16 +00:00
3f1ed8690d Reformat documentation 2026-02-18 15:30:53 +00:00
0a6318784c Fix wrong attribute name in shared dir docs (id -> tag) 2026-02-18 15:26:07 +00:00
7802ea1407 Update README.md, add screenshot 2026-02-18 15:02:54 +00:00
4b231b91db README.md: Add section on video playback, update features 2026-02-18 11:07:11 +00:00
2df7b5d9fb Update README.md with clearer warning 2026-02-18 10:57:06 +00:00
61ca26690a Remove vm-switch and bufferbloat-test
The vm-switch experiment for VM-to-VM networking via vhost-user-net
didn't work out — it performs poorly under load, with busy connections
saturating the buffer and causing high latency for others.

Removes the vm-switch Rust crate, bufferbloat-test suite, all NixOS
module integration (options, services, networking, assertions, scripts),
and documentation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 23:41:13 +00:00