{ 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' = lib.importTOML ../hosts/known-hosts.toml; # TODO: eww known-hosts = lib.pipe known-hosts' [ (lib.flip lib.removeAttrs ["__default__"]) (lib.mapAttrs (name: host: lib.recursiveUpdate (known-hosts'."__default__" or {}) host )) ]; hostNames = attrNames known-hosts; thisHost = known-hosts.${config.networking.fqdn}; thisHostIsBuilder = thisHost.buildMachine.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}" = { mode = "0440"; group = "nix-community-builder"; }; }; users.groups.nix-community-builder = {}; }) # 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; }