config/profiles/remote-builders.nix

90 lines
3.3 KiB
Nix

{ config, lib, ... }:
# TODO: make a remote-build user on nixos boxes, instead of giving access to pbsds
# TODO: https://exozy.me/quickstart
# TODO: https://github.com/winterqt/darwin-build-box
let
inherit (builtins) map fromTOML readFile elem attrNames attrValues;
inherit (lib) mkIf;
known-hosts' = fromTOML (readFile ../hosts/known-hosts.toml); # TODO: eww
known-hosts = lib.pipe known-hosts' [
(lib.filterAttrs (name: host: name != "__default__"))
(lib.mapAttrs (name: host:
lib.recursiveUpdate (known-hosts'."__default__" or {}) host
))
];
hostNames = attrNames known-hosts;
thisHost = known-hosts.${config.networking.fqdn};
thisHostIsBuilder = thisHost.maxJobs > 0;
thisHostIsHopHost = builtins.elem config.networking.fqdn (lib.forEach (attrValues known-hosts) (host: host.ssh.proxyJump or null));
thisHostIsConsumer = thisHost.ssh ? userPublicKey;
mkRemoteConfig = fqdn: let
thatHost = known-hosts.${fqdn};
thatJump = known-hosts.${thatHost.ssh.proxyJump};
buildMachine = thatHost.buildMachine // {
hostName = fqdn;
sshUser = thatHost.ssh.listenUser;
};
thatHostIsBuilder = thatHost.buildMachine.maxJobs > 0;
thatHostIsConsumer = thatHost.ssh ? userPublicKey && thisHostIsBuilder;
thatHostIsThis = fqdn == config.networking.fqdn;
in mkIf (!thatHostIsThis) ( lib.mkMerge [
# out
(lib.mkIf (thisHostIsConsumer && thatHostIsBuilder) {
nix.buildMachines = [ buildMachine ];
})
# out or jump
(lib.mkIf (thisHostIsConsumer && thatHost.ssh ? listenPublicKey) {
programs.ssh.knownHosts.${fqdn}.publicKey = thatHost.ssh.listenPublicKey;
# TODO: use nix.buildMachines.*.publicHostKey ?
# timeouts are great when remote is unresponsive. nix doesn't care, lix is way and tests each remote only once
programs.ssh.extraConfig = ''
Host ${fqdn}
ConnectTimeout 3
Port ${builtins.toString thatHost.ssh.listenPort}
${lib.optionalString (thatHost.ssh ? proxyJump) ''
ProxyJump ${thatJump.ssh.listenUser}@${thatHost.ssh.proxyJump}:${builtins.toString thatJump.ssh.listenPort}
''}
${lib.optionalString (thatHost.ssh ? userPrivateKey) ''
IdentityFile ${thatHost.ssh.userPrivateKey}
''}
'';
sops.secrets = lib.mkIf (lib.hasPrefix "/run/secrets/" (thatHost.ssh.userPrivateKey or "")) {
"${lib.removePrefix "/run/secrets/" thatHost.ssh.userPrivateKey}" = {};
};
})
# in
(mkIf ((thisHostIsBuilder || thisHostIsHopHost) && thatHostIsConsumer) {
users.users.${thisHost.ssh.listenUser} = {
isSystemUser = lib.mkDefault (!config.users.users.${thisHost.ssh.listenUser}.isNormalUser);
openssh.authorizedKeys.keys = [ thatHost.ssh.userPublicKey ];
group = lib.mkOptionDefault "nogroup";
};
})
(mkIf (thisHostIsBuilder && thatHostIsConsumer) {
nix.settings.allowed-users = [ thisHost.ssh.listenUser ];
nix.settings.trusted-users = [ thisHost.ssh.listenUser ];
})
]);
in {
nix.distributedBuilds = true;
# TODO: Allow setting speedFactor for local builds, as local is currently fixed to 0
# https://github.com/NixOS/nix/issues/2457
# useful when the builder has a faster internet connection than i do
nix.settings.builders-use-substitutes = true;
imports = lib.forEach hostNames mkRemoteConfig;
}