{ config, pkgs, lib, vmixLib, ... }: with lib; { options = { autostart = mkOption { type = types.bool; default = false; description = "Start VM on host boot."; }; enable = mkOption { type = types.bool; default = true; description = "Enable/disable VM service creation."; }; vnc = { enable = mkOption { type = types.bool; default = false; description = "Enable VNC."; }; addr = mkOption { type = types.str; default = "0.0.0.0"; description = "VNC bind address inside the VM namespace."; }; port = mkOption { type = types.ints.between 5900 5999; default = 5900; description = "VNC TCP port inside the VM namespace."; }; forwardHostPort = mkOption { type = types.nullOr types.port; default = null; description = "Optional host TCP port to auto-forward to this VM VNC port."; }; websocketPort = mkOption { type = types.nullOr types.port; default = null; description = "Optional websocket port for VNC (for noVNC-style clients)."; }; passwordFile = mkOption { type = types.nullOr types.str; default = null; description = "Path to a runtime file containing the VNC password. When set, VNC auth is enabled via password-secret."; }; sharePolicy = mkOption { type = types.enum [ "allow-exclusive" "force-shared" "ignore" ]; default = "allow-exclusive"; description = "VNC client sharing policy."; }; }; spice = { enable = mkOption { type = types.bool; default = false; description = "Enable SPICE display server."; }; port = mkOption { type = types.int; default = 5930; description = "SPICE TCP port inside the VM namespace."; }; forwardHostPort = mkOption { type = types.nullOr types.port; default = null; description = "Optional host TCP port to auto-forward to this VM SPICE port."; }; addr = mkOption { type = types.str; default = "0.0.0.0"; description = "SPICE bind address inside the VM namespace."; }; passwordFile = mkOption { type = types.nullOr types.str; default = null; description = "Path to a runtime file containing SPICE password. When set, ticketing is enabled automatically, otherwise ticketing is disabled."; }; agent.enable = mkOption { type = types.bool; default = true; description = "Enable SPICE guest agent channel (clipboard/resolution helpers)."; }; usbRedir = { enable = mkOption { type = types.bool; default = false; description = "Enable SPICE USB redirection channels."; }; channels = mkOption { type = types.ints.between 1 16; default = 4; description = "Number of SPICE USB redirection channels to expose."; }; }; displayDevice = mkOption { type = types.enum [ "virtio" "qxl" "std" "none" ]; default = "qxl"; description = "QEMU -vga type to use with SPICE (qxl, virtio, std, none)."; }; vgamem = mkOption { type = types.nullOr types.int; default = null; description = "Video memory in MB for QXL device. When set, uses -device qxl-vga instead of -vga qxl."; }; }; nographic = mkOption { type = types.bool; default = true; description = "Run QEMU without a graphical window (-nographic)."; }; cpu.cores = mkOption { type = types.int; default = 2; description = "Number of CPU cores."; }; cpu.model = mkOption { type = types.str; default = "host"; description = "CPU model."; }; cpu.hideVirtualized = mkOption { type = types.bool; default = true; description = "Hide hypervisor from guest. Prevents GPU driver Code 43 errors by stripping hypervisor CPUID leaf."; }; kvm = mkOption { type = types.bool; default = true; description = "Enable KVM."; }; arch = mkOption { type = types.str; default = "x86_64"; description = "Architecture of the VM."; }; pc.type = mkOption { type = types.str; default = "q35"; description = "PC type."; }; bios.efi = mkOption { type = types.bool; default = true; description = "Enable EFI BIOS."; }; bios.tpm = mkOption { type = types.bool; default = false; description = "Enable TPM BIOS."; }; mem.size = mkOption { type = types.int; default = 1024; description = "Memory size in MB."; }; mem.balloon = mkOption { type = types.bool; default = false; description = "Enable memory ballooning."; }; disks.os.file = mkOption { type = types.nullOr types.path; default = null; description = "Path to the OS disk image. Null for ISO-only VMs. For Windows, use a vmixLib.windows.* image — config auto-detects via _vmixOsType metadata."; }; disks.os.persist = mkOption { type = types.bool; default = false; description = "Persist OS disk changes. The store image is copied to persistPath on first boot and QEMU writes to that mutable copy."; }; disks.os.persistPath = mkOption { type = types.str; default = ""; description = "Mutable path for the persistent OS disk (e.g. /storage/vms/myvm/os.qcow2). Required when persist = true."; }; disks.iso.file = mkOption { type = types.nullOr (types.either types.path types.str); description = "Path to the ISO file. Can be a Nix store path or a string path to a local file."; default = null; }; disks.add = mkOption { default = {}; type = types.attrsOf (types.submodule { options = { file = mkOption { type = types.str; description = "String literal path to the additional disk."; }; format = mkOption { type = types.str; description = "raw/qcow2 etc"; }; mounts = mkOption { type = types.attrsOf types.str; description = "Mount points for the additional disk."; }; opts = mkOption { type = types.str; description = "additional options in QEMU args for this disk"; }; }; }); description = "Additional disks."; }; shares = mkOption { default = {}; type = types.attrsOf (types.submodule { options = { source = mkOption { type = types.path; description = "Source path for the shared directory."; }; target = mkOption { type = types.str; description = "Target path inside the VM for the shared directory."; }; }; }); description = "Shared directories."; }; disks.bus = mkOption { type = types.str; default = "virtio"; description = "Bus type for the disks."; }; boot.order = mkOption { type = types.listOf (types.enum [ "os" "iso" "net" "floppy" ]); description = "Boot order."; default = [ "os" "iso" ]; }; boot.menu = mkOption { type = types.bool; default = false; description = "Enable boot menu."; }; nicModel = mkOption { type = types.str; default = "virtio-net-pci"; description = "QEMU NIC device model (e.g. virtio-net-pci, e1000)."; }; windows = { enable = mkOption { type = types.bool; default = false; description = "Enable Windows-optimized QEMU flags. Auto-enabled when disks.os.file carries _vmixOsType = \"windows\" metadata."; }; }; tpm = { stateDir = mkOption { type = types.str; default = "/tmp"; description = "Directory for TPM state persistence. Set to a /storage path for persistence across reboots."; }; }; pci.passthrough = mkOption { type = types.listOf types.str; default = []; description = "PCI device addresses to passthrough via VFIO (e.g. [\"0000:03:00.0\" \"0000:03:00.1\"])."; }; pci.romFile = mkOption { type = types.nullOr types.path; default = null; description = "GPU VBIOS ROM file for the first passthrough device. Required when GPU PCI ROM BAR doesn't expose the full VBIOS (common with AMD Navi+)."; }; usb.hostDevices = mkOption { default = []; type = types.listOf (types.submodule { options = { vendorId = mkOption { type = types.str; description = "USB vendor ID (e.g. \"1d6b\")."; }; productId = mkOption { type = types.str; description = "USB product ID (e.g. \"0104\")."; }; }; }); description = "USB host devices to passthrough to the VM."; }; networks.user.enable = mkOption { type = types.bool; default = false; description = "enable qemu user networking"; }; networks.lans = mkOption { default = {}; type = types.attrsOf (types.submodule { options = { mac = mkOption { type = types.str; description = "MAC address for the LAN interface."; }; ip = mkOption { type = types.nullOr (types.strMatching vmixLib.network.regex.ipv4); default = null; description = "assign static IP from the lan pool."; }; }; }); description = "LAN interfaces."; }; networks.macvtaps = mkOption { default = {}; type = types.attrsOf (types.submodule { options = { mac = mkOption { type = types.nullOr types.str; default = null; description = "MAC address for the MACVTap interface."; }; }; }); description = "MACVTap interfaces."; }; }; }