clan/modules/remote_builders.nix

126 lines
3.4 KiB
Nix

{
lib,
config,
pkgs,
self,
...
}:
let
inherit (lib)
filterAttrs
mkEnableOption
mkIf
mapAttrsToList
attrNames
map
concatLines
mkOption
types
;
cfg = config.our.buildMachines;
others = filterAttrs (n: v: n != config.networking.hostName) self.nixosConfigurations;
max = a: b: if a > b then a else b;
mkBuilder =
hostName: attrs:
let
config' = attrs.config;
cfg' = config'.our.buildMachines;
pkgs' = attrs.pkgs;
in
mkIf cfg'.enable {
hostName = hostName;
sshUser = "remotebuild";
# CPU architecture of the builder, and the operating system it runs.
# If your builder supports multiple architectures
# (e.g. search for "binfmt" for emulation),
systems = [ pkgs'.system ] ++ config'.boot.binfmt.emulatedSystems;
# Nix custom ssh-variant that avoids lots of "trusted-users" settings pain
protocol = "ssh-ng";
# default is 1 but may keep the builder idle in between builds
maxJobs = 3;
speedFactor = max (cfg'.speedFactor - cfg.speedFactor + 1) 1;
supportedFeatures = cfg'.supportedFeatures;
mandatoryFeatures = [ ];
};
buildMachines = mapAttrsToList mkBuilder others;
remotebuildKeys = mapAttrsToList (
_name: attrs: attrs.config.clan.core.vars.generators.remotebuild.files."ssh.id_ed25519.pub".value
) others;
mkMatch = host:
''
Match User remotebuild Host ${host}
IdentityFile ${config.clan.core.vars.generators.remotebuild.files."ssh.id_ed25519".path}
'';
othersName = attrNames others;
sshConfig = concatLines (map mkMatch othersName);
in
{
options.our.buildMachines = {
enable = mkEnableOption "Use this machine as a remoteBuilder for others and vice versa.";
supportedFeatures = mkOption {
type = types.listOf (
types.oneOf [
"nixos-test"
"benchmark"
"big-parallel"
"kvm"
]
);
default = [ ];
description = ''
kvm | Everything which builds inside a vm, like NixOS tests
nixos-test | Machine can run NixOS tests
big-parallel | kernel config, libreoffice, evolution, llvm and chromium
benchmark | Machine can generate metrics (means the builds usually takes the same amount of time)
'';
};
speedFactor = mkOption {
type = types.int;
default = 1;
description = "How fast is the builder compared to your local machine";
};
};
config = mkIf cfg.enable {
users.users.remotebuild = {
isNormalUser = true;
createHome = false;
group = "remotebuild";
openssh.authorizedKeys.keys = remotebuildKeys;
};
users.groups.remotebuild = { };
clan.core.vars.generators.remotebuild = {
files."ssh.id_ed25519" = { };
files."ssh.id_ed25519.pub".secret = false;
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519
'';
};
programs.ssh.extraConfig = sshConfig;
nix = {
buildMachines = buildMachines;
# required, otherwise remote buildMachines above aren't used
distributedBuilds = true;
# optional, useful when the builder has a faster internet connection than yours
settings = {
builders-use-substitutes = true;
trusted-users = [ "remotebuild" ];
};
};
};
}