{ flake, config, lib, hostName, ... }:
with lib;
let
  cfg = config.nix.buildServers;
  secretName = name: "nix-ssh-builder-${name}-private";
  buildHostName = host: "nix-ssh-builder-${host}";
in {
  options = {
    nix = {
      buildServers = mkOption {
        type = types.attrsOf (types.submodule {
          options = {
            address = mkOption {
              type = types.str;
              description = "Address of buildserver";
            };
            system = mkOption {
              type = types.nullOr types.str;
              default = null;
              example = "x86_64-linux";
              description = ''
                The system type the build machine can execute derivations on.
                Either this attribute or systems must be
                present, where system takes precedence if
                both are set.
              '';
            };
            systems = mkOption {
              type = types.listOf types.str;
              default = [];
              example = [ "x86_64-linux" "aarch64-linux" ];
              description = ''
                The system types the build machine can execute derivations on.
                Either this attribute or system must be
                present, where system takes precedence if
                both are set.
              '';
            };
            maxJobs = mkOption {
              type = types.int;
              default = 1;
              description = ''
                The number of concurrent jobs the build machine supports. The
                build machine will enforce its own limits, but this allows hydra
                to schedule better since there is no work-stealing between build
                machines.
              '';
            };
            speedFactor = mkOption {
              type = types.int;
              default = 1;
              description = ''
                The relative speed of this builder. This is an arbitrary integer
                that indicates the speed of this builder, relative to other
                builders. Higher is faster.
              '';
            };
            mandatoryFeatures = mkOption {
              type = types.listOf types.str;
              default = [];
              example = [ "big-parallel" ];
              description = ''
                A list of features mandatory for this builder. The builder will
                be ignored for derivations that don't require all features in
                this list. All mandatory features are automatically included in
                supportedFeatures.
              '';
            };
            supportedFeatures = mkOption {
              type = types.listOf types.str;
              default = [];
              example = [ "kvm" "big-parallel" ];
              description = ''
                A list of features supported by this builder. The builder will
                be ignored for derivations that require features not in this
                list.
              '';
            };
          };
        });
        default = {};
        description = "Buildservers to use";
      };
    };
  };
  config = mkIf (cfg != {}) {
    programs.ssh.extraConfig = concatMapStringsSep "\n" ({ name, value }: ''
      Host ${buildHostName name}
        User nix-ssh-builder
        HostName ${value.address}
        IdentitiesOnly yes
        IdentityFile ${config.sops.secrets.${secretName name}.path}
        ControlMaster auto
        ControlPath /run/nix-ssh-builder-master-%r@%n:%p
        ControlPersist 30m
        Compression yes
        ForwardAgent no
        ServerAliveInterval 6
        ServerAliveCountMax 10
    '') (mapAttrsToList nameValuePair cfg);
    sops.secrets = mapAttrs' (name: hCfg: nameValuePair (secretName name) { sopsFile = ../system-profiles/build-server/clients + "/${hostName}/private"; format = "binary"; }) cfg;
    nix = {
      distributedBuilds = true;
      extraOptions = ''
        builders-use-substitutes = true
      '';
      buildMachines = mapAttrsToList (name: hCfg: { hostName = buildHostName name; inherit (hCfg) system systems maxJobs speedFactor mandatoryFeatures supportedFeatures; }) cfg;
    };
  };
}