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