vmsilo/flake.nix
Davíð Steinn Geirsson 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

269 lines
8.5 KiB
Nix

{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
wayland-proxy-virtwl = {
url = "git+https://git.dsg.is/dsg/wayland-proxy-virtwl.git?submodules=1";
inputs.nixpkgs.follows = "nixpkgs";
};
crosvm = {
url = "git+https://git.dsg.is/dsg/crosvm.git?ref=vmsilo&submodules=1";
inputs.nixpkgs.follows = "nixpkgs";
};
vhost-device = {
url = "git+https://git.dsg.is/dsg/vhost-device.git";
inputs.nixpkgs.follows = "nixpkgs";
};
cloud-hypervisor = {
url = "git+https://git.dsg.is/dsg/cloud-hypervisor.git";
inputs.nixpkgs.follows = "nixpkgs";
};
usbip-rs = {
url = "git+https://git.dsg.is/dsg/usbip-rs.git";
inputs.nixpkgs.follows = "nixpkgs";
};
treefmt-nix = {
url = "github:numtide/treefmt-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs =
{
self,
nixpkgs,
wayland-proxy-virtwl,
crosvm,
vhost-device,
cloud-hypervisor,
usbip-rs,
treefmt-nix,
}:
let
usbip-rs-input = usbip-rs;
eachSystem = nixpkgs.lib.genAttrs [
"x86_64-linux"
"aarch64-linux"
];
# Build NixOS-based rootfs as qcow2 image
makeRootfsNixos =
system:
{
guestPrograms ? [ ],
guestConfig ? [ ],
usbip-rs ? usbip-rs-input.packages.${system}.default,
}:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.callPackage (import ./rootfs-nixos) {
inherit guestPrograms guestConfig usbip-rs;
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${system}.default;
};
# Build vmsilo-balloond Rust binary
buildVmsiloBalloond =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-balloond";
version = "0.1.0";
src = ./vmsilo-balloond;
cargoLock = {
lockFile = ./vmsilo-balloond/Cargo.lock;
};
};
# Build vmsilo-dbus-proxy Rust binaries
buildVmsiloDbusProxy =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-dbus-proxy";
version = "0.1.0";
src = ./vmsilo-dbus-proxy;
cargoLock = {
lockFile = ./vmsilo-dbus-proxy/Cargo.lock;
};
};
# Build vmsilo-wayland-seccontext Rust binary
buildVmsiloWaylandSeccontext =
system:
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.rustPlatform.buildRustPackage {
pname = "vmsilo-wayland-seccontext";
version = "0.1.0";
src = ./vmsilo-wayland-seccontext;
cargoLock = {
lockFile = ./vmsilo-wayland-seccontext/Cargo.lock;
};
nativeBuildInputs = with pkgs; [ pkg-config ];
buildInputs = with pkgs; [ wayland ];
};
# treefmt configuration
treefmtConfig = {
projectRootFile = "flake.nix";
programs.nixfmt.enable = true;
};
in
{
formatter = eachSystem (
system:
(treefmt-nix.lib.evalModule nixpkgs.legacyPackages.${system} treefmtConfig).config.build.wrapper
);
packages = eachSystem (system: {
default = makeRootfsNixos system { };
rootfs-nixos = makeRootfsNixos system { };
vmsilo-balloond = buildVmsiloBalloond system;
vmsilo-dbus-proxy = buildVmsiloDbusProxy system;
vmsilo-wayland-seccontext = buildVmsiloWaylandSeccontext system;
"cloud-hypervisor" = cloud-hypervisor.packages.${system}.cloud-hypervisor;
decoration-tests =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.stdenv.mkDerivation {
pname = "decoration-tests";
version = "0.1.0";
src = ./wayland_decoration_tests;
nativeBuildInputs = with pkgs; [
wayland-scanner
pkg-config
];
buildInputs = [ pkgs.wayland ];
makeFlags = [
"WAYLAND_PROTOCOLS=${pkgs.wayland-protocols}/share/wayland-protocols"
"PLASMA_WAYLAND_PROTOCOLS=${pkgs.kdePackages.plasma-wayland-protocols}/share/plasma-wayland-protocols"
"WLR_PROTOCOLS=${pkgs.wlr-protocols}/share/wlr-protocols"
];
installPhase = ''
mkdir -p $out/bin
cp test-csd-request test-no-decoration-protocol test-mode-none test-server-decoration-none test-fullscreen test-layer-shell test-large-popup test-subsurface-overflow test-ssd-request $out/bin/
'';
};
sommelier = nixpkgs.legacyPackages.${system}.callPackage ./packages/sommelier.nix { };
});
devShells = eachSystem (system: {
default =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
buildInputs = with pkgs; [
# Rust toolchain
cargo
rustc
rust-analyzer
rustfmt
clippy
# Build dependencies
pkg-config
];
RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
};
decoration-tests =
let
pkgs = nixpkgs.legacyPackages.${system};
in
pkgs.mkShell {
buildInputs = with pkgs; [
wayland
wayland-protocols
kdePackages.plasma-wayland-protocols
wlr-protocols
wayland-scanner
pkg-config
gcc
];
WAYLAND_PROTOCOLS = "${pkgs.wayland-protocols}/share/wayland-protocols";
PLASMA_WAYLAND_PROTOCOLS = "${pkgs.kdePackages.plasma-wayland-protocols}/share/plasma-wayland-protocols";
WLR_PROTOCOLS = "${pkgs.wlr-protocols}/share/wlr-protocols";
};
});
# Helper function for building custom NixOS rootfs
lib.makeRootfsNixos = makeRootfsNixos;
nixosModules.default =
{
config,
pkgs,
lib,
...
}:
{
imports = [ ./modules ];
# Inject dependencies when module is enabled
config = lib.mkIf config.programs.vmsilo.enable {
programs.vmsilo._internal = {
crosvm = crosvm.packages.${pkgs.stdenv.hostPlatform.system}.default;
"cloud-hypervisor" = cloud-hypervisor.packages.${pkgs.stdenv.hostPlatform.system}.cloud-hypervisor;
vmsilo-wayland-seccontext = buildVmsiloWaylandSeccontext pkgs.stdenv.hostPlatform.system;
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${pkgs.stdenv.hostPlatform.system}.default;
sommelier = pkgs.callPackage ./packages/sommelier.nix { };
vhost-device-sound = vhost-device.packages.${pkgs.stdenv.hostPlatform.system}.vhost-device-sound;
vmsilo-balloond = buildVmsiloBalloond pkgs.stdenv.hostPlatform.system;
vmsilo-dbus-proxy = buildVmsiloDbusProxy pkgs.stdenv.hostPlatform.system;
"usbip-rs" = usbip-rs-input.packages.${pkgs.stdenv.hostPlatform.system}.default;
};
};
};
nixosModules.optionalGuestSettings =
# Dark Breeze theme for Qt and GTK apps. Not used by default.
{
config,
pkgs,
lib,
...
}:
{
config = {
environment.etc."xdg/gtk-3.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Breeze-Dark
gtk-application-prefer-dark-theme=true
'';
environment.etc."xdg/gtk-4.0/settings.ini".text = ''
[Settings]
gtk-theme-name=Breeze-Dark
gtk-application-prefer-dark-theme=true
'';
# plasma-integration reads kdeglobals for color scheme and style.
# xdg-desktop-portal-kde reads Colors:Window BackgroundNormal to
# report org.freedesktop.appearance color-scheme preference.
environment.etc."xdg/kdeglobals".text = ''
[General]
ColorScheme=BreezeDark
widgetStyle=breeze
[Icons]
Theme=breeze-dark
[KDE]
widgetStyle=breeze
[Colors:Window]
BackgroundNormal=32,35,38
'';
};
};
};
}