fix(shell): migrate ssh to the settings API; reset stale zcompdump

The home-manager bump deprecated programs.ssh.addKeysToAgent /
matchBlocks / the implicit default block. Move to programs.ssh.settings
with enableDefaultConfig = false, carrying the old defaults under
settings."*" plus AddKeysToAgent, the Darwin UseKeychain, and the
code.emmathe.dev (Port 30009) host. Silences all three ssh warnings.

Also drop ~/.zcompdump on each activation: a stale dump caches /nix/store
paths to completion functions, and once a rebuild or the weekly nh GC
removes them compinit fails with "_git: function definition file not
found" for every completion. Deleting it forces a fresh rebuild from the
current fpath.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Emma Thorpe
2026-06-10 11:55:46 +01:00
parent faf2242539
commit 7b41584d5c
+41 -14
View File
@@ -218,24 +218,51 @@
# manages ~/.ssh/config on the personal hosts. # manages ~/.ssh/config on the personal hosts.
programs.ssh = { programs.ssh = {
enable = true; enable = true;
addKeysToAgent = "yes"; # The module's built-in default "*" block is being deprecated; opt out and
# macOS: also cache in the login keychain (no prompt after first unlock). # carry the defaults we want ourselves under settings."*".
# UseKeychain is unknown to non-Apple openssh, so only emit it on Darwin. enableDefaultConfig = false;
extraConfig = lib.optionalString pkgs.stdenv.hostPlatform.isDarwin '' settings = {
UseKeychain yes # Global defaults (rendered last, as ssh_config wants). AddKeysToAgent
''; # adds the key on first use so the passphrase is typed once per session.
# Gitea remote (the flake's origin) -- required on every host. Pins the "*" = {
# dedicated key so the right identity is offered. identitiesOnly avoids AddKeysToAgent = "yes";
# "too many authentication failures" when the agent holds several keys. ForwardAgent = false;
matchBlocks."code.emmathe.dev" = { Compression = false;
user = "git"; ServerAliveInterval = 0;
port = 30009; # Gitea listens on a non-default SSH port ServerAliveCountMax = 3;
identityFile = "~/.ssh/code.emmathe.dev"; HashKnownHosts = false;
identitiesOnly = true; UserKnownHostsFile = "~/.ssh/known_hosts";
ControlMaster = "no";
ControlPath = "~/.ssh/master-%r@%n:%p";
ControlPersist = "no";
}
# macOS: also cache the passphrase in the login keychain. UseKeychain is
# unknown to non-Apple openssh, so only emit it on Darwin.
// lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
UseKeychain = "yes";
};
# Gitea remote (the flake's origin) -- required on every host. Port 30009
# is non-default; pin the dedicated key (identitiesOnly avoids "too many
# authentication failures" when the agent holds several keys).
"code.emmathe.dev" = {
User = "git";
Port = 30009;
IdentityFile = "~/.ssh/code.emmathe.dev";
IdentitiesOnly = true;
};
}; };
}; };
# Run a user ssh-agent on Linux (macOS provides one via launchd). EDaaS also # Run a user ssh-agent on Linux (macOS provides one via launchd). EDaaS also
# enables this in the work module; both being true merges cleanly. # enables this in the work module; both being true merges cleanly.
services.ssh-agent.enable = lib.mkIf pkgs.stdenv.hostPlatform.isLinux true; services.ssh-agent.enable = lib.mkIf pkgs.stdenv.hostPlatform.isLinux true;
# Drop the zsh completion dump on every activation. A stale ~/.zcompdump
# caches /nix/store paths to completion functions; once a rebuild or GC (the
# weekly nh clean) removes them, compinit fails with "_git: function
# definition file not found" for every completion. Deleting it forces a fresh
# rebuild from the current fpath on the next shell.
home.activation.resetZcompdump = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
$DRY_RUN_CMD rm -f "$HOME"/.zcompdump* "''${XDG_CACHE_HOME:-$HOME/.cache}"/zsh/.zcompdump* 2>/dev/null || true
'';
} }