{ config, pkgs, lib, ... }: with lib; { options.proxmox = { qemuConf = { # essential configs boot = mkOption { type = types.str; default = ""; example = "order=scsi0;net0"; description = lib.mdDoc '' Default boot device. PVE will try all devices in its default order if this value is empty. ''; }; scsihw = mkOption { type = types.str; default = "virtio-scsi-pci"; example = "lsi"; description = lib.mdDoc '' SCSI controller type. Must be one of the supported values given in ''; }; virtio0 = mkOption { type = types.str; default = "local-lvm:vm-9999-disk-0"; example = "ceph:vm-123-disk-0"; description = lib.mdDoc '' Configuration for the default virtio disk. It can be used as a cue for PVE to autodetect the target sotrage. This parameter is required by PVE even if it isn't used. ''; }; ostype = mkOption { type = types.str; default = "l26"; description = lib.mdDoc '' Guest OS type ''; }; cores = mkOption { type = types.ints.positive; default = 1; description = lib.mdDoc '' Guest core count ''; }; memory = mkOption { type = types.ints.positive; default = 1024; description = lib.mdDoc '' Guest memory in MB ''; }; # optional configs name = mkOption { type = types.str; default = "nixos-${config.system.nixos.label}"; description = lib.mdDoc '' VM name ''; }; net0 = mkOption { type = types.commas; default = "virtio=00:00:00:00:00:00,bridge=vmbr0,firewall=1"; description = lib.mdDoc '' Configuration for the default interface. When restoring from VMA, check the "unique" box to ensure device mac is randomized. ''; }; serial0 = mkOption { type = types.str; default = "socket"; example = "/dev/ttyS0"; description = lib.mdDoc '' Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0), or create a unix socket on the host side (use qm terminal to open a terminal connection). ''; }; agent = mkOption { type = types.bool; apply = x: if x then "1" else "0"; default = true; description = lib.mdDoc '' Expect guest to have qemu agent running ''; }; }; qemuExtraConf = mkOption { type = with types; attrsOf (oneOf [ str int ]); default = {}; example = literalExpression ''{ cpu = "host"; onboot = 1; }''; description = lib.mdDoc '' Additional options appended to qemu-server.conf ''; }; filenameSuffix = mkOption { type = types.str; default = config.proxmox.qemuConf.name; example = "999-nixos_template"; description = lib.mdDoc '' Filename of the image will be vzdump-qemu-''${filenameSuffix}.vma.zstd. This will also determine the default name of the VM on restoring the VMA. Start this value with a number if you want the VMA to be detected as a backup of any specific VMID. ''; }; }; config = let cfg = config.proxmox; cfgLine = name: value: '' ${name}: ${builtins.toString value} ''; cfgFile = fileName: properties: pkgs.writeTextDir fileName '' # generated by NixOS ${lib.concatStrings (lib.mapAttrsToList cfgLine properties)} #qmdump#map:virtio0:drive-virtio0:local-lvm:raw: ''; in { system.build.VMA = import ../../lib/make-disk-image.nix { name = "proxmox-${cfg.filenameSuffix}"; postVM = let # Build qemu with PVE's patch that adds support for the VMA format vma = pkgs.qemu_kvm.overrideAttrs ( super: rec { # proxmox's VMA patch doesn't work with qemu 7.0 yet version = "6.2.0"; src = pkgs.fetchurl { url= "https://download.qemu.org/qemu-${version}.tar.xz"; hash = "sha256-aOFdjkWsVjJuC5pK+otJo9/oq6NIgiHQmMhGmLymW0U="; }; patches = let rev = "b37b17c286da3d32945fbee8ee4fd97a418a50db"; path = "debian/patches/pve/0026-PVE-Backup-add-vma-backup-format-code.patch"; vma-patch = pkgs.fetchpatch { url = "https://git.proxmox.com/?p=pve-qemu.git;a=blob_plain;h=${rev};f=${path}"; hash = "sha256-siuDWDUnM9Zq0/L2Faww3ELAOUHhVIHu5RAQn6L4Atc="; }; in [ vma-patch ]; buildInputs = super.buildInputs ++ [ pkgs.libuuid ]; }); in '' ${vma}/bin/vma create "vzdump-qemu-${cfg.filenameSuffix}.vma" \ -c ${cfgFile "qemu-server.conf" (cfg.qemuConf // cfg.qemuExtraConf)}/qemu-server.conf drive-virtio0=$diskImage rm $diskImage ${pkgs.zstd}/bin/zstd "vzdump-qemu-${cfg.filenameSuffix}.vma" mv "vzdump-qemu-${cfg.filenameSuffix}.vma.zst" $out/ ''; format = "raw"; inherit config lib pkgs; }; boot = { growPartition = true; kernelParams = [ "console=ttyS0" ]; loader.grub.device = lib.mkDefault "/dev/vda"; loader.timeout = 0; initrd.availableKernelModules = [ "uas" "virtio_blk" "virtio_pci" ]; }; fileSystems."/" = { device = "/dev/disk/by-label/nixos"; autoResize = true; fsType = "ext4"; }; services.qemuGuest.enable = lib.mkDefault true; }; }