summary refs log tree commit diff
path: root/nixos/modules/virtualisation/proxmox-image.nix
diff options
context:
space:
mode:
Diffstat (limited to 'nixos/modules/virtualisation/proxmox-image.nix')
-rw-r--r--nixos/modules/virtualisation/proxmox-image.nix169
1 files changed, 169 insertions, 0 deletions
diff --git a/nixos/modules/virtualisation/proxmox-image.nix b/nixos/modules/virtualisation/proxmox-image.nix
new file mode 100644
index 00000000000..c537d5aed44
--- /dev/null
+++ b/nixos/modules/virtualisation/proxmox-image.nix
@@ -0,0 +1,169 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+{
+  options.proxmox = {
+    qemuConf = {
+      # essential configs
+      boot = mkOption {
+        type = types.str;
+        default = "";
+        example = "order=scsi0;net0";
+        description = ''
+          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 = ''
+          SCSI controller type. Must be one of the supported values given in
+          <link xlink:href="https://pve.proxmox.com/wiki/Qemu/KVM_Virtual_Machines"/>
+        '';
+      };
+      virtio0 = mkOption {
+        type = types.str;
+        default = "local-lvm:vm-9999-disk-0";
+        example = "ceph:vm-123-disk-0";
+        description = ''
+          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 = ''
+          Guest OS type
+        '';
+      };
+      cores = mkOption {
+        type = types.ints.positive;
+        default = 1;
+        description = ''
+          Guest core count
+        '';
+      };
+      memory = mkOption {
+        type = types.ints.positive;
+        default = 1024;
+        description = ''
+          Guest memory in MB
+        '';
+      };
+
+      # optional configs
+      name = mkOption {
+        type = types.str;
+        default = "nixos-${config.system.nixos.label}";
+        description = ''
+          VM name
+        '';
+      };
+      net0 = mkOption {
+        type = types.commas;
+        default = "virtio=00:00:00:00:00:00,bridge=vmbr0,firewall=1";
+        description = ''
+          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 = ''
+          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 = ''
+          Expect guest to have qemu agent running
+        '';
+      };
+    };
+    qemuExtraConf = mkOption {
+      type = with types; attrsOf (oneOf [ str int ]);
+      default = {};
+      example = literalExpression ''{
+        cpu = "host";
+        onboot = 1;
+      }'';
+      description = ''
+        Additional options appended to qemu-server.conf
+      '';
+    };
+    filenameSuffix = mkOption {
+      type = types.str;
+      default = config.proxmox.qemuConf.name;
+      example = "999-nixos_template";
+      description = ''
+        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: {
+          patches = let
+            rev = "cc707c362ea5c8d832aac270d1ffa7ac66a8908f";
+            path = "debian/patches/pve/0025-PVE-Backup-add-vma-backup-format-code.patch";
+            vma-patch = pkgs.fetchpatch {
+              url = "https://git.proxmox.com/?p=pve-qemu.git;a=blob_plain;hb=${rev};f=${path}";
+              sha256 = "1z467xnmfmry3pjy7p34psd5xdil9x0apnbvfz8qbj0bf9fgc8zf";
+            };
+          in super.patches ++ [ 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;
+  };
+}