11 ./disk-size-option.nix
12 ../image/file-options.nix
13 (lib.mkRenamedOptionModuleWith {
33 example = "order=scsi0;net0";
35 Default boot device. PVE will try all devices in its default order if this value is empty.
40 default = "virtio-scsi-single";
43 SCSI controller type. Must be one of the supported values given in
44 <https://pve.proxmox.com/wiki/Qemu/KVM_Virtual_Machines>
49 default = "local-lvm:vm-9999-disk-0";
50 example = "ceph:vm-123-disk-0";
52 Configuration for the default virtio disk. It can be used as a cue for PVE to autodetect the target storage.
53 This parameter is required by PVE even if it isn't used.
64 type = types.ints.positive;
71 type = types.ints.positive;
84 Select BIOS implementation (seabios = Legacy BIOS, ovmf = UEFI).
91 default = "nixos-${config.system.nixos.label}";
96 additionalSpace = mkOption {
101 additional disk space to be added to the image if diskSize "auto"
105 bootSize = mkOption {
110 Size of the boot partition. Is only used if partitionTableType is
111 either "efi" or "hybrid".
116 default = "virtio=00:00:00:00:00:00,bridge=vmbr0,firewall=1";
118 Configuration for the default interface. When restoring from VMA, check the
119 "unique" box to ensure device mac is randomized.
125 example = "/dev/ttyS0";
127 Create a serial device inside the VM (n is 0 to 3), and pass through a host serial device (i.e. /dev/ttyS0),
128 or create a unix socket on the host side (use qm terminal to open a terminal connection).
133 apply = x: if x then "1" else "0";
136 Expect guest to have qemu agent running
140 qemuExtraConf = mkOption {
148 example = literalExpression ''
155 Additional options appended to qemu-server.conf
158 partitionTableType = mkOption {
166 Partition table type to use. See make-disk-image.nix partitionTableType for details.
167 Defaults to 'legacy' for 'proxmox.qemuConf.bios="seabios"' (default), other bios values defaults to 'efi'.
168 Use 'hybrid' to build grub-based hybrid bios+efi images.
170 default = if config.proxmox.qemuConf.bios == "seabios" then "legacy" else "efi";
171 defaultText = lib.literalExpression ''if config.proxmox.qemuConf.bios == "seabios" then "legacy" else "efi"'';
174 filenameSuffix = mkOption {
176 default = config.proxmox.qemuConf.name;
177 example = "999-nixos_template";
179 Filename of the image will be vzdump-qemu-''${filenameSuffix}.vma.zstd.
180 This will also determine the default name of the VM on restoring the VMA.
181 Start this value with a number if you want the VMA to be detected as a backup of
190 Whether the VM should accept cloud init configurations from PVE.
193 defaultStorage = mkOption {
194 default = "local-lvm";
198 Default storage name for cloud init drive.
206 Bus/device to which the cloud init drive is attached.
214 cfg = config.proxmox;
215 cfgLine = name: value: ''
216 ${name}: ${builtins.toString value}
218 virtio0Storage = builtins.head (builtins.split ":" cfg.qemuConf.virtio0);
220 fileName: properties:
221 pkgs.writeTextDir fileName ''
223 ${lib.concatStrings (lib.mapAttrsToList cfgLine properties)}
224 #qmdump#map:virtio0:drive-virtio0:${virtio0Storage}:raw:
226 inherit (cfg) partitionTableType;
227 supportEfi = partitionTableType == "efi" || partitionTableType == "hybrid";
229 partitionTableType == "legacy"
230 || partitionTableType == "hybrid"
231 || partitionTableType == "legacy+gpt";
232 hasBootPartition = partitionTableType == "efi" || partitionTableType == "hybrid";
233 hasNoFsPartition = partitionTableType == "hybrid" || partitionTableType == "legacy+gpt";
238 assertion = config.boot.loader.systemd-boot.enable -> config.proxmox.qemuConf.bios == "ovmf";
239 message = "systemd-boot requires 'ovmf' bios";
242 assertion = partitionTableType == "efi" -> config.proxmox.qemuConf.bios == "ovmf";
243 message = "'efi' disk partitioning requires 'ovmf' bios";
246 assertion = partitionTableType == "legacy" -> config.proxmox.qemuConf.bios == "seabios";
247 message = "'legacy' disk partitioning requires 'seabios' bios";
250 assertion = partitionTableType == "legacy+gpt" -> config.proxmox.qemuConf.bios == "seabios";
251 message = "'legacy+gpt' disk partitioning requires 'seabios' bios";
254 image.baseName = lib.mkDefault "vzdump-qemu-${cfg.filenameSuffix}";
255 image.extension = "vma.zst";
256 system.build.image = config.system.build.VMA;
257 system.build.VMA = import ../../lib/make-disk-image.nix {
258 name = "proxmox-${cfg.filenameSuffix}";
259 baseName = config.image.baseName;
260 inherit (cfg) partitionTableType;
263 # Build qemu with PVE's patch that adds support for the VMA format
265 (pkgs.qemu_kvm.override {
267 pulseSupport = false;
272 smartcardSupport = false;
273 spiceSupport = false;
274 ncursesSupport = false;
275 libiscsiSupport = false;
278 seccompSupport = false;
279 guestAgentSupport = false;
282 # Check https://github.com/proxmox/pve-qemu/tree/master for the version
283 # of qemu and patch to use
285 src = pkgs.fetchurl {
286 url = "https://download.qemu.org/qemu-${version}.tar.xz";
287 hash = "sha256-MnCKxmww2MiSYz6paMdxwcdtWX1w3erSGg0izPOG2mk=";
290 # Proxmox' VMA tool is published as a particular patch upon QEMU
292 pkgs.fetchFromGitHub {
295 rev = "14afbdd55f04d250bd679ca1ad55d3f47cd9d4c8";
296 hash = "sha256-lSJQA5SHIHfxJvMLIID2drv2H43crTPMNIlIT37w9Nc=";
298 }/debian/patches/pve/0027-PVE-Backup-add-vma-backup-format-code.patch"
301 buildInputs = super.buildInputs ++ [ pkgs.libuuid ];
302 nativeBuildInputs = super.nativeBuildInputs ++ [ pkgs.perl ];
307 ${vma}/bin/vma create "${config.image.baseName}.vma" \
309 cfgFile "qemu-server.conf" (cfg.qemuConf // cfg.qemuExtraConf)
310 }/qemu-server.conf drive-virtio0=$diskImage
312 ${pkgs.zstd}/bin/zstd "${config.image.baseName}.vma"
313 mv "${config.image.fileName}" $out/
315 mkdir -p $out/nix-support
316 echo "file vma $out/${config.image.fileName}" > $out/nix-support/hydra-build-products
318 inherit (cfg.qemuConf) additionalSpace bootSize;
319 inherit (config.virtualisation) diskSize;
321 inherit config lib pkgs;
325 growPartition = true;
326 kernelParams = [ "console=ttyS0" ];
328 device = lib.mkDefault (
329 if (hasNoFsPartition || supportBios) then
330 # Even if there is a separate no-fs partition ("/dev/disk/by-partlabel/no-fs" i.e. "/dev/vda2"),
331 # which will be used the bootloader, do not set it as loader.grub.device.
332 # GRUB installation fails, unless the whole disk is selected.
337 efiSupport = lib.mkDefault supportEfi;
338 efiInstallAsRemovable = lib.mkDefault supportEfi;
342 initrd.availableKernelModules = [
350 device = "/dev/disk/by-label/nixos";
354 fileSystems."/boot" = lib.mkIf hasBootPartition {
355 device = "/dev/disk/by-label/ESP";
359 networking = mkIf cfg.cloudInit.enable {
360 hostName = mkForce "";
365 cloud-init = mkIf cfg.cloudInit.enable {
367 network.enable = true;
369 sshd.enable = mkDefault true;
370 qemuGuest.enable = true;
373 proxmox.qemuExtraConf.${cfg.cloudInit.device} = "${cfg.cloudInit.defaultStorage}:vm-9999-cloudinit,media=cdrom";