summary refs log blame commit diff
path: root/nixos/modules/virtualisation/proxmox-image.nix
blob: e07d1d1eb3fc658a202550ec73035f4e4a6a70bf (plain) (tree)
































































































































                                                                                                                      








                                                                         
                       

                                                                                         
                                         

                                                                                              
              

                           
                                                              
 





























                                                                                                                        
{ 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: 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;
  };
}