diff --git a/clanModules/sshd/roles/server.nix b/clanModules/sshd/roles/server.nix index c66e21acd..22aacae6f 100644 --- a/clanModules/sshd/roles/server.nix +++ b/clanModules/sshd/roles/server.nix @@ -9,15 +9,13 @@ let domains = stringSet config.clan.sshd.certificate.searchDomains; - signArgs = builtins.concatStringsSep " " ( - builtins.map ( - domain: "-n ${lib.escapeShellArg "${config.clan.core.machineName}.${domain}"}" - ) domains - ); cfg = config.clan.sshd; in { imports = [ ../shared.nix ]; + options = { + clan.sshd.hostKeys.rsa.enable = lib.mkEnableOption "Generate RSA host key"; + }; config = { services.openssh = { enable = true; @@ -27,12 +25,17 @@ in cfg.certificate.searchDomains != [ ] ) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path; - hostKeys = [ - { - path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path; - type = "ed25519"; - } - ]; + hostKeys = + [ + { + path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path; + type = "ed25519"; + } + ] + ++ lib.optional cfg.hostKeys.rsa.enable { + path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path; + type = "rsa"; + }; }; clan.core.vars.generators.openssh = { files."ssh.id_ed25519" = { }; @@ -47,6 +50,19 @@ in ''; }; + clan.core.vars.generators.openssh-rsa = lib.mkIf config.clan.sshd.hostKeys.rsa.enable { + files."ssh.id_rsa" = { }; + files."ssh.id_rsa.pub".secret = false; + migrateFact = "openssh"; + runtimeInputs = [ + pkgs.coreutils + pkgs.openssh + ]; + script = '' + ssh-keygen -t rsa -b 4096 -N "" -f $out/ssh.id_rsa + ''; + }; + clan.core.vars.generators.openssh-cert = lib.mkIf (cfg.certificate.searchDomains != [ ]) { files."ssh.id_ed25519-cert.pub".secret = false; dependencies = [ @@ -65,7 +81,8 @@ in ssh-keygen \ -s $in/openssh-ca/id_ed25519 \ -I ${config.clan.core.machineName} \ - ${builtins.toString signArgs} \ + -h \ + -n ${lib.concatMapStringsSep "," (d: "${config.clan.core.machineName}.${d}") domains} \ $in/openssh/ssh.id_ed25519.pub mv $in/openssh/ssh.id_ed25519-cert.pub $out/ssh.id_ed25519-cert.pub ''; diff --git a/pkgs/clan-cli/clan_cli/git.py b/pkgs/clan-cli/clan_cli/git.py index d893edf2e..e0a12c90c 100644 --- a/pkgs/clan-cli/clan_cli/git.py +++ b/pkgs/clan-cli/clan_cli/git.py @@ -57,7 +57,17 @@ def _commit_file_to_git( :param commit_message: The commit message. :raises ClanError: If the file is not in the git repository. """ - with locked_open(repo_dir / ".git" / "clan.lock", "w+"): + dotgit = repo_dir / ".git" + real_git_dir = repo_dir / ".git" + # resolve worktree + if dotgit.is_file(): + actual_git_dir = dotgit.read_text().strip() + if not actual_git_dir.startswith("gitdir: "): + msg = f"Invalid .git file: {actual_git_dir}" + raise ClanError(msg) + real_git_dir = repo_dir / actual_git_dir[len("gitdir: ") :] + + with locked_open(real_git_dir / "clan.lock", "w+"): for file_path in file_paths: cmd = run_cmd( ["git"], diff --git a/pkgs/clan-cli/clan_cli/vars/_types.py b/pkgs/clan-cli/clan_cli/vars/_types.py index f06f68ffc..c3442dca7 100644 --- a/pkgs/clan-cli/clan_cli/vars/_types.py +++ b/pkgs/clan-cli/clan_cli/vars/_types.py @@ -76,7 +76,7 @@ class StoreBase(ABC): def backend_collision_error(self, folder: Path) -> None: msg = ( - f"Var folder {folder} exists but doesn't look like a {self.store_name} secret." + f"Var folder {folder} exists but doesn't look like a {self.store_name} secret.\n" "Potentially a leftover from another backend. Please delete it manually." ) raise ClanError(msg)