{
  inputs,
  lib,
  ...
}:

let
  inherit (lib)
    attrValues
    concatLists
    mapAttrs
    mkOption
    evalModules
    ;
  inherit (lib.attrsets) concatMapAttrs genAttrs;

  addDefaultDeployment =
    deployments: deployments // { default = concatLists (attrValues deployments); };

  makeResourceModule = vmName: {
    _module.args = { inherit inputs; };
    imports = [
      ./common/resource.nix
      (./. + "/${vmName}")
    ];
    fediversityVm.name = vmName;
  };

  makeDeployments = mapAttrs (
    _: 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 vmName)
        ];
      });
    }
  );

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

  makeConfigurations = concatMapAttrs (
    _: vmNames:
    genAttrs vmNames (
      vmName:
      inputs.nixpkgs.lib.nixosSystem {
        modules = [
          (evalModules {
            modules = [
              nixops4ResourceNixosMockOptions
              (makeResourceModule vmName)
            ];
          }).config.nixos.module
        ];
      }
    )
  );

  machines = {
    git = [
      "vm02116"
      "fedi300"
    ];
    web = [ "vm02187" ];
    other = [
      "vm02179"
      "vm02186"
    ];
  };

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

  nixops4Deployments = makeDeployments (addDefaultDeployment machines);
  flake.nixosConfigurations = makeConfigurations machines;
}