From f997b72f4027d32b79b6edb7af220594eccab93f Mon Sep 17 00:00:00 2001 From: Git Sagar Date: Sun, 7 Jun 2026 10:39:35 +0530 Subject: [PATCH 1/2] only create macvtaps service when macvtaps are configured Prevents unnecessary VM restarts on deploy when no macvtaps are used. Co-Authored-By: Claude Opus 4.6 (1M context) --- nixos/vms/config.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/nixos/vms/config.nix b/nixos/vms/config.nix index cae926d..6be8a44 100644 --- a/nixos/vms/config.nix +++ b/nixos/vms/config.nix @@ -231,7 +231,7 @@ let in lib.optionalAttrs (cfg.enable) { "vm.vmix@${vmCfg.name}" = rec { - bindsTo = [ "net.vmix@${spaceName}.target" "macvtaps.vm.vmix@${vmCfg.name}.service" ]; + bindsTo = [ "net.vmix@${spaceName}.target" ] ++ lib.optional (allMacvtaps != []) "macvtaps.vm.vmix@${vmCfg.name}.service"; unitConfig.JoinsNamespaceOf = "ns.net.vmix@${spaceName}.service"; after = bindsTo; path = with pkgs; [ iproute2 qemu gawk coreutils ]; @@ -248,9 +248,9 @@ let ProtectSystem = lib.mkForce false; SupplementaryGroups = [ "kvm" ]; }; - wantedBy = lib.mkIf vmCfg.autostart [ "multi-user.target" ]; + wantedBy = lib.mkIf vmCfg.autostart [ "multi-user.target" ]; }; - + } // lib.optionalAttrs (allMacvtaps != []) { "macvtaps.vm.vmix@${vmCfg.name}" = rec { bindsTo = [ "net.vmix@${spaceName}.target" ]; after = bindsTo; From e196160aac7a84a65e105597e61dfa73001c1964 Mon Sep 17 00:00:00 2001 From: Git Sagar Date: Sun, 7 Jun 2026 10:46:32 +0530 Subject: [PATCH 2/2] add README with usage, architecture, and examples Co-Authored-By: Claude Opus 4.6 (1M context) --- README.md | 131 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..14ad5c5 --- /dev/null +++ b/README.md @@ -0,0 +1,131 @@ +# vmix + +Composable QEMU VM image building and orchestration for NixOS. + +## What it does + +vmix provides: +- **Image building** — reproducible Linux (Debian) and Windows qcow2 images via Nix derivations +- **NixOS module** — declarative VM management with QEMU in network namespaces +- **CLI tool** — build, copy-to-disk, and run images from the command line + +## Usage + +### As a flake input + +```nix +# flake.nix +inputs.vmix.url = "git+https://git.sagar.ch/dotfiles/vmix.nix.git"; + +# In your NixOS configuration (or globally via serverFunctions) +imports = [ inputs.vmix.nixosModules.default ]; + +# Use vmixLib via overlay +nixpkgs.overlays = [ inputs.vmix.overlays.default ]; +# Then: pkgs.vmixLib.linux, pkgs.vmixLib.windows, pkgs.vmixLib.network +``` + +### As a CLI + +```bash +# Enter dev shell +nix develop + +# Build an image +vmix build --image windows.images.win10.laptop \ + --generalize username=User,password=secret,hostname=PC + +# Write to local disk +vmix copy --image windows.images.win10.laptop \ + --generalize username=User,password=secret \ + --to-disk /dev/sda + +# Write to remote disk (streamed via SSH + LZ4) +vmix copy --image windows.images.win10.laptop \ + --generalize username=User,password=secret \ + --to-remote-disk root@10.10.10.100:/dev/nvme0n1 + +# Boot a built image with QEMU +vmix run ./result --mem 8192 --smp 8 --ahci +``` + +## Flake outputs + +| Output | Description | +|--------|-------------| +| `overlays.default` | Nix overlay exposing `pkgs.vmixLib` | +| `nixosModules.default` | NixOS module for declarative VM management | +| `lib.x86_64-linux` | Library functions (images + network utilities) | +| `packages.x86_64-linux.default` | vmix CLI tool | +| `apps.x86_64-linux.default` | Runnable vmix app | + +## Repository structure + +``` +flake.nix # Flake entry point +module.nix # NixOS module export +overlay.nix # Nix overlay (vmixLib pinned to nixpkgs 25-11) +cli.nix # CLI tool (build, copy, run) + +lib/ + default.nix # Exports: images (linux + windows) + network + network.nix # IPv4/CIDR utilities + images/ + linux/ # Debian image building + customization + windows/ # Windows image building + customization + helpers/ # makeImage, customizeImage, makeWinISO, etc. + templates/ # Registry tweaks, app installers, essentials + drivers/ # VirtIO, AMD GPU drivers + win10/ # Windows 10 LTSC images + win11/ # Windows 11 images + +nixos/ + default.nix # NixOS module entry point + networks/ # Network namespace management (LAN, WAN, macvtap) + vms/ # VM lifecycle management (QEMU, tap devices, DHCP) +``` + +## Image building + +### Windows pipeline + +1. `makeImage` — unattended install from upstream ISO via QEMU +2. `customizeImageFold` — apply modular templates (registry, apps, drivers) +3. `generalize` — sysprep + OOBE for deployment to real hardware + +### Linux pipeline + +1. Fetch upstream Debian cloud image +2. `customizeImageFold` — apply templates via `virt-customize` + +### Key patterns + +- **`customizeImageFold`** — `builtins.foldl'` over templates for composable layered images +- **`_vmixOsType`** — all images carry `"linux"` or `"windows"` metadata for auto-detection +- **Offline registry** — Windows templates use `ControlSet001` for offline `virt-win-reg --merge` + +## NixOS module + +Declare VMs and networks: + +```nix +vmix.namespaces."lab" = { + networks.lan1 = { + subnet = "10.99.1.0/24"; + dhcp.enable = true; + }; + vms.myvm = { + image = pkgs.vmixLib.linux.images.debian.v12.upstream; + memory = 2048; + cores = 2; + interfaces.lan1 = { ip = "10.99.1.10"; }; + autostart = true; + }; +}; +``` + +Features: +- Network namespaces with WAN (veth), LAN (bridge + dnsmasq), macvtap +- ACPI graceful shutdown via QMP socket +- 9p shares with auto-created mount targets +- Conditional macvtap service (only created when macvtaps are configured)