{
  self,
  inputs,
  lib,
  ...
}:

let
  inherit (builtins) readDir;
  inherit (lib)
    attrNames
    mkOption
    evalModules
    mapAttrs
    ;
  inherit (lib.attrsets) genAttrs;

  ## Given a machine's name and whether it is a test VM, make a resource module,
  ## except for its missing provider. (Depending on the use of that resource, we
  ## will provide a different one.)
  makeResourceModule =
    { vmName, isTestVm }:
    {
      _module.args = { inherit inputs; };
      imports = [
        ./common/resource.nix
        (if isTestVm then ./test-machines + "/${vmName}" else ./machines + "/${vmName}")
      ];
      fediversityVm.name = vmName;
    };

  ## Given a list of machine names, make a deployment with those machines'
  ## configurations as resources.
  makeDeployment =
    vmNames:
    { providers, ... }:
    {
      providers.local = inputs.nixops4.modules.nixops4Provider.local;
      resources = genAttrs vmNames (vmName: {
        type = providers.local.exec;
        imports = [
          inputs.nixops4-nixos.modules.nixops4Resource.nixos
          (makeResourceModule {
            inherit vmName;
            isTestVm = false;
          })
        ];
      });
    };
  makeDeployment' = vmName: makeDeployment [ vmName ];

  ## Given an attrset of test configurations (key = test machine name, value =
  ## NixOS configuration module), make a deployment with those machines'
  ## configurations as resources.
  makeTestDeployment =
    vmConfigs:
    { providers, ... }:
    {
      providers.local = inputs.nixops4.modules.nixops4Provider.local;
      resources = mapAttrs (vmName: vmConfig: {
        type = providers.local.exec;
        imports = [
          inputs.nixops4-nixos.modules.nixops4Resource.nixos
          (makeResourceModule {
            inherit vmName;
            isTestVm = false;
          })
          { nixos.module = vmConfig; }
          { nixos.module = self.nixosModules.fediversity; }
        ];
      }) vmConfigs;
    };

  nixops4ResourceNixosMockOptions = {
    ## NOTE: We allow the use of a few options from
    ## `inputs.nixops4-nixos.modules.nixops4Resource.nixos` such that we can
    ## reuse modules that make use of them.
    ##
    ## REVIEW: We can probably do much better and cleaner. On the other hand,
    ## this is only needed to expose NixOS configurations for provisioning
    ## purposes, and eventually all of this should be handled by NixOps4.
    options = {
      nixos.module = mkOption { }; # NOTE: not just `nixos` otherwise merging will go wrong
      nixpkgs = mkOption { };
      ssh = mkOption { };
    };
  };

  makeResourceConfig =
    vm:
    (evalModules {
      modules = [
        nixops4ResourceNixosMockOptions
        (makeResourceModule vm)
      ];
    }).config;

  ## Given a VM name, make a NixOS configuration for this machine.
  makeConfiguration =
    isTestVm: vmName:
    inputs.nixpkgs.lib.nixosSystem {
      modules = [
        (makeResourceConfig { inherit vmName isTestVm; }).nixos.module
      ];
    };

  makeVmOptions = isTestVm: vmName: {
    inherit ((makeResourceConfig { inherit vmName isTestVm; }).fediversityVm)
      proxmox
      vmId
      sockets
      cores
      memory
      hostPublicKey
      unsafeHostPrivateKey
      ;
  };

  machines = attrNames (readDir ./machines);
  testMachineConfigurations = import ./test-machines/configuration.nix;

in
{
  flake.lib.makeInstallerIso = import ./makeInstallerIso.nix;

  ## - Each normal or test machine gets a NixOS configuration.
  ## - Each normal or test machine gets a VM options entry.
  ## - Each normal machine gets a deployment.
  ## - We add a “default” deployment with all normal machines.
  ## - We add a “test” deployment with all test machines.
  nixops4Deployments = genAttrs machines makeDeployment' // {
    default = makeDeployment machines;
    test = makeTestDeployment testMachineConfigurations;
  };
  flake.nixosConfigurations =
    genAttrs machines (makeConfiguration false)
    // genAttrs (attrNames testMachineConfigurations) (makeConfiguration true);
  flake.vmOptions =
    genAttrs machines (makeVmOptions false)
    // genAttrs (attrNames testMachineConfigurations) (makeVmOptions true);
}