Implements a vhost-user network switch daemon that enables L2 networking between VMs in the same vmNetwork. The switch uses a router/client topology where: - Each network has exactly one router VM - Client VMs can only communicate through the router - MAC addresses are discovered via inotify-watched config directory The daemon implements the vhost-user protocol to provide virtio-net backends that crosvm connects to via --vhost-user sockets. Key components: - vm-switch Rust crate with MAC parsing, frame routing, and vhost-user backend - NixOS module integration with per-network systemd services - Automatic daemon startup when VMs are added to a network Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
129 lines
3.4 KiB
Nix
129 lines
3.4 KiB
Nix
{
|
|
inputs = {
|
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
wayland-proxy-virtwl = {
|
|
url = "git+https://git.dsg.is/davidlowsec/wayland-proxy-virtwl.git?submodules=1";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
crosvm = {
|
|
#url = "git+https://git.dsg.is/davidlowsec/crosvm.git?ref=dsg&submodules=1";
|
|
url = "git+file:///home/david/git/crosvm?ref=dsg&submodules=1";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
treefmt-nix = {
|
|
url = "github:numtide/treefmt-nix";
|
|
inputs.nixpkgs.follows = "nixpkgs";
|
|
};
|
|
};
|
|
|
|
outputs =
|
|
{
|
|
self,
|
|
nixpkgs,
|
|
wayland-proxy-virtwl,
|
|
crosvm,
|
|
treefmt-nix,
|
|
}:
|
|
let
|
|
eachSystem = nixpkgs.lib.genAttrs [
|
|
"x86_64-linux"
|
|
"aarch64-linux"
|
|
];
|
|
|
|
# Build NixOS-based rootfs as qcow2 image
|
|
makeRootfsNixos =
|
|
system:
|
|
{
|
|
guestPrograms ? [ ],
|
|
guestConfig ? { },
|
|
}:
|
|
let
|
|
pkgs = nixpkgs.legacyPackages.${system};
|
|
in
|
|
pkgs.callPackage (import ./rootfs-nixos) {
|
|
inherit guestPrograms guestConfig;
|
|
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${system}.default;
|
|
};
|
|
|
|
# Build vm-switch Rust binary
|
|
buildVmSwitch =
|
|
system:
|
|
let
|
|
pkgs = nixpkgs.legacyPackages.${system};
|
|
in
|
|
pkgs.rustPlatform.buildRustPackage {
|
|
pname = "vm-switch";
|
|
version = "0.1.0";
|
|
src = ./vm-switch;
|
|
cargoLock = {
|
|
lockFile = ./vm-switch/Cargo.lock;
|
|
outputHashes = {
|
|
"vhost-0.15.0" = "sha256-HZIHv2nGO9me2YHqjR0uGcDBM6/fje2dx0L5AGY3Oxg=";
|
|
};
|
|
};
|
|
};
|
|
|
|
# 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 { };
|
|
vm-switch = buildVmSwitch system;
|
|
});
|
|
|
|
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}";
|
|
};
|
|
});
|
|
|
|
# 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.qubes-lite.enable {
|
|
programs.qubes-lite._internal = {
|
|
crosvm = crosvm.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
|
wayland-proxy-virtwl = wayland-proxy-virtwl.packages.${pkgs.stdenv.hostPlatform.system}.default;
|
|
vm-switch = buildVmSwitch pkgs.stdenv.hostPlatform.system;
|
|
};
|
|
};
|
|
};
|
|
};
|
|
}
|