{ config, pkgs, hostName, lib, ... }: with lib; let cfg = config.system.rebuild-machine; sshConfig = pkgs.writeText "config" '' UserKnownHostsFile ${knownHostsFile} Host ${cfg.repoHost} User ${cfg.repoUser} IdentityFile ${if isNull cfg.sopsConfig then cfg.repoPrivkey else config.sops.secrets."${cfg.sopsName}".path} IdentitiesOnly yes ''; knownHostsFile = pkgs.writeText "known_hosts" (concatMapStringsSep "\n" (kPath: cfg.repoHost + " " + readFile kPath) (attrValues cfg.repoPubkeys)); rebuildScript = pkgs.stdenv.mkDerivation { name = "rebuild-${hostName}"; src = ./rebuild-machine.zsh; buildInputs = with pkgs; [ makeWrapper ]; phases = [ "buildPhase" "installPhase" ]; inherit (pkgs) zsh coreutils openssh; inherit (cfg) flake scriptName; nixosRebuild = config.system.build.nixos-rebuild; inherit (config.security) wrapperDir; inherit sshConfig; buildPhase = '' substituteAll $src rebuild-machine.zsh ''; installPhase = '' mkdir -p $out/bin install -m 0755 rebuild-machine.zsh $out/bin/${cfg.scriptName} ''; }; in { options = { system.rebuild-machine = { scriptName = mkOption { type = types.str; default = "rebuild-${hostName}"; description = '' Name of the script wrapping nixos-rebuild ''; }; flake = mkOption { type = types.nullOr types.str; default = "git+ssh://${cfg.repoHost}/nixos?ref=flakes#${hostName}"; description = '' The Flake URI of the NixOS configuration to build. ''; }; repoHost = mkOption { type = types.str; default = "git.yggdrasil.li"; }; repoUser = mkOption { type = types.str; default = "gitolite"; }; repoPubkeys = mkOption { type = types.attrsOf types.path; default = genAttrs ["rsa" "ed25519"] (kType: ./ssh-pub + "/${cfg.repoHost}-${kType}.pub"); }; repoPrivkey = mkOption { type = types.path; default = ./ssh + "/${hostName}/private"; }; sopsName = mkOption { type = types.nullOr types.str; default = "rebuild-machines"; }; sopsConfig = mkOption { type = types.nullOr types.attrs; default = { format = "binary"; }; }; }; }; config = { assertions = [ { assertion = isNull cfg.sopsConfig || (!(isNull cfg.sopsName)); message = "If option sopsConfig is not null option sopsName may not be null"; } ]; sops.secrets = lib.mkIf (!(isNull cfg.sopsConfig)) { "${cfg.sopsName}" = { sopsFile = cfg.repoPrivkey; } // cfg.sopsConfig; }; environment.systemPackages = [ rebuildScript ]; }; }