Commit 9bf3c5122dab
Changed files (2)
home
common
shell
lib
home/common/shell/openssh.nix
@@ -20,137 +20,138 @@ in
programs.ssh = {
enable = true;
enableDefaultConfig = false;
- matchBlocks = {
- "*" = {
- serverAliveInterval = 60;
- hashKnownHosts = true;
- userKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts";
- addKeysToAgent = "confirm";
- controlMaster = "auto";
- controlPersist = "10m";
- controlPath = "${config.home.homeDirectory}/.ssh/master-%C";
- };
- # Shpool session aliases (https://bower.sh/you-might-not-need-tmux)
- # Usage: ssh <host>/<session-name>
- # Example: ssh rhea.home/music, ssh aomi.home/dev
- }
- // (
- # Generate shpool session aliases for each machine dynamically
+ matchBlocks =
let
- inherit (pkgs) lib;
- mkShpoolAliases =
- _: machine:
- let
- # Get hostname identifiers (e.g., "rhea.home", "rhea.vpn", "rhea.sbr.pm")
- identifiers = builtins.filter (
- x: (lib.hasSuffix ".home" x) || (lib.hasSuffix ".vpn" x) || (lib.hasSuffix ".sbr.pm" x)
- ) (libx.sshHostIdentifier machine);
- # For each identifier, create a Host block with /* wildcard
- mkSessionBlock = id: {
- name = "${id}/*";
- value = {
- hostname =
- if (lib.hasSuffix ".vpn" id) then
- builtins.head machine.net.vpn.ips
- else if (lib.hasSuffix ".home" id) then
- builtins.head machine.net.ips
- else
- id;
- extraOptions = {
- RemoteCommand = "shpool-ssh-wrapper $(echo '%k' | cut -d/ -f2-)";
- # RemoteCommand = "bash -ic '[ -f ~/.local/share/kitty-ssh-kitten/zsh/kitty-integration ] && source ~/.local/share/kitty-ssh-kitten/zsh/kitty-integration 2>/dev/null; exec shpool-ssh-wrapper $(echo \"%k\" | cut -d/ -f2-)'";
- RequestTTY = "yes";
- };
- };
- };
- in
- builtins.listToAttrs (map mkSessionBlock identifiers);
+ # Critical infra hosts that need touch-required key
+ criticalInfraOverrides = lib.optionalAttrs hasFido2Keys {
+ "athena.home".identityFile = "~/.ssh/id_critical_infra_sk";
+ "athena.vpn".identityFile = "~/.ssh/id_critical_infra_sk";
+ "athena.sbr.pm".identityFile = "~/.ssh/id_critical_infra_sk";
+ "demeter.home".identityFile = "~/.ssh/id_critical_infra_sk";
+ "demeter.vpn".identityFile = "~/.ssh/id_critical_infra_sk";
+ "demeter.sbr.pm".identityFile = "~/.ssh/id_critical_infra_sk";
+ "kerkouane.vpn".identityFile = "~/.ssh/id_critical_infra_sk";
+ "kerkouane.sbr.pm".identityFile = "~/.ssh/id_critical_infra_sk";
+ };
+ # Special case for aomi
+ aomiOverrides = lib.optionalAttrs isAomi {
+ "kerkouane.vpn" = {
+ identityFile = "~/.ssh/id_ed25519";
+ identitiesOnly = true;
+ };
+ };
in
- # Merge all shpool aliases for all machines
- lib.attrsets.mergeAttrsList (lib.attrsets.mapAttrsToList mkShpoolAliases globals.machines)
- )
- // {
- "github.com" = {
- hostname = "github.com";
- user = "git";
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_github_sk";
- extraOptions = {
- controlMaster = "auto";
- controlPersist = "360";
- };
- };
- "gitlab.com" = {
- hostname = "gitlab.com";
- user = "git";
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_gitlab_sk";
- extraOptions = {
- controlMaster = "auto";
- controlPersist = "360";
- };
- };
- "codeberg.org" = {
- hostname = "codeberg.org";
- user = "git";
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_codeberg_sk";
- extraOptions = {
- controlMaster = "auto";
- controlPersist = "360";
- };
- };
- "git.sr.ht" = {
- hostname = "git.sr.ht";
- user = "git";
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_srht_sk";
- extraOptions = {
- controlMaster = "auto";
- controlPersist = "360";
- };
- };
- "*.redhat.com" = {
- user = "vdemeest";
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_redhat_sk";
- };
- "bootstrap.ospqa.com" = {
- forwardAgent = true;
- };
- "192.168.1.*" = {
- forwardAgent = true;
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_homelab_sk";
- extraOptions = {
- StrictHostKeyChecking = "no";
- UserKnownHostsFile = "/dev/null";
- };
- };
- "10.100.0.*" = {
- forwardAgent = true;
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_homelab_sk";
- };
- # Critical infrastructure - uses id_critical_infra_sk (touch-required) by default
- # For no-touch convenience, use: ssh -i ~/.ssh/id_homelab_sk <host>
- "athena.home" = {
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_critical_infra_sk";
- };
- "athena.vpn" = {
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_critical_infra_sk";
- };
- "demeter.home" = {
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_critical_infra_sk";
- };
- "demeter.vpn" = {
- identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_critical_infra_sk";
- };
- "kerkouane.vpn" = {
- identityFile =
- if hasFido2Keys then
- "~/.ssh/id_critical_infra_sk"
- else if isAomi then
- "~/.ssh/id_ed25519"
- else
- null;
- identitiesOnly = isAomi;
- };
- }
- // libx.sshConfigs globals.machines;
+ lib.recursiveUpdate (
+ {
+ "*" = {
+ serverAliveInterval = 60;
+ hashKnownHosts = true;
+ userKnownHostsFile = "${config.home.homeDirectory}/.ssh/known_hosts";
+ addKeysToAgent = "confirm";
+ controlMaster = "auto";
+ controlPersist = "10m";
+ controlPath = "${config.home.homeDirectory}/.ssh/master-%C";
+ };
+ # Shpool session aliases (https://bower.sh/you-might-not-need-tmux)
+ # Usage: ssh <host>/<session-name>
+ # Example: ssh rhea.home/music, ssh aomi.home/dev
+ }
+ // (
+ # Generate shpool session aliases for each machine dynamically
+ let
+ inherit (pkgs) lib;
+ mkShpoolAliases =
+ _: machine:
+ let
+ # Get hostname identifiers (e.g., "rhea.home", "rhea.vpn", "rhea.sbr.pm")
+ identifiers = builtins.filter (
+ x: (lib.hasSuffix ".home" x) || (lib.hasSuffix ".vpn" x) || (lib.hasSuffix ".sbr.pm" x)
+ ) (libx.sshHostIdentifier machine);
+ # For each identifier, create a Host block with /* wildcard
+ mkSessionBlock = id: {
+ name = "${id}/*";
+ value = {
+ hostname =
+ if (lib.hasSuffix ".vpn" id) then
+ builtins.head machine.net.vpn.ips
+ else if (lib.hasSuffix ".home" id) then
+ builtins.head machine.net.ips
+ else
+ id;
+ extraOptions = {
+ RemoteCommand = "shpool-ssh-wrapper $(echo '%k' | cut -d/ -f2-)";
+ # RemoteCommand = "bash -ic '[ -f ~/.local/share/kitty-ssh-kitten/zsh/kitty-integration ] && source ~/.local/share/kitty-ssh-kitten/zsh/kitty-integration 2>/dev/null; exec shpool-ssh-wrapper $(echo \"%k\" | cut -d/ -f2-)'";
+ RequestTTY = "yes";
+ };
+ };
+ };
+ in
+ builtins.listToAttrs (map mkSessionBlock identifiers);
+ in
+ # Merge all shpool aliases for all machines
+ lib.attrsets.mergeAttrsList (lib.attrsets.mapAttrsToList mkShpoolAliases globals.machines)
+ )
+ # Generated configs for all machines (sets default id_homelab_sk)
+ // libx.sshConfigs globals.machines
+ # External hosts (new entries, not overrides)
+ // {
+ "github.com" = {
+ hostname = "github.com";
+ user = "git";
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_github_sk";
+ extraOptions = {
+ controlMaster = "auto";
+ controlPersist = "360";
+ };
+ };
+ "gitlab.com" = {
+ hostname = "gitlab.com";
+ user = "git";
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_gitlab_sk";
+ extraOptions = {
+ controlMaster = "auto";
+ controlPersist = "360";
+ };
+ };
+ "codeberg.org" = {
+ hostname = "codeberg.org";
+ user = "git";
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_codeberg_sk";
+ extraOptions = {
+ controlMaster = "auto";
+ controlPersist = "360";
+ };
+ };
+ "git.sr.ht" = {
+ hostname = "git.sr.ht";
+ user = "git";
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_srht_sk";
+ extraOptions = {
+ controlMaster = "auto";
+ controlPersist = "360";
+ };
+ };
+ "*.redhat.com" = {
+ user = "vdemeest";
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_redhat_sk";
+ };
+ "bootstrap.ospqa.com" = {
+ forwardAgent = true;
+ };
+ "192.168.1.*" = {
+ forwardAgent = true;
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_homelab_sk";
+ extraOptions = {
+ StrictHostKeyChecking = "no";
+ UserKnownHostsFile = "/dev/null";
+ };
+ };
+ "10.100.0.*" = {
+ forwardAgent = true;
+ identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_homelab_sk";
+ };
+ }
+ ) (lib.recursiveUpdate criticalInfraOverrides aomiOverrides);
extraConfig = ''
# IdentityAgent /run/user/1000/yubikey-agent/yubikey-agent.sock
GlobalKnownHostsFile ~/.ssh/ssh_known_hosts ~/.ssh/ssh_known_hosts.redhat ~/.ssh/ssh_known_hosts.mutable
lib/functions.nix
@@ -153,8 +153,12 @@ let
else if (lib.strings.hasSuffix ".home" x) then
builtins.head machine.net.ips
else
+ # .sbr.pm uses the hostname directly (DNS resolution)
x;
forwardAgent = false;
+ # Use FIDO2 homelab key for all homelab hosts
+ identityFile = "~/.ssh/id_homelab_sk";
+ identitiesOnly = true;
# Disable IdentityAgent only for aomi.home (prevents yubikey prompts in TRAMP)
extraOptions = lib.optionalAttrs (x == "aomi.home") {
IdentityAgent = "none";
@@ -162,9 +166,12 @@ let
};
})
(
- builtins.filter (x: (lib.strings.hasSuffix ".home" x) || (lib.strings.hasSuffix ".vpn" x)) (
- sshHostIdentifier machine
- )
+ builtins.filter (
+ x:
+ (lib.strings.hasSuffix ".home" x)
+ || (lib.strings.hasSuffix ".vpn" x)
+ || (lib.strings.hasSuffix ".sbr.pm" x)
+ ) (sshHostIdentifier machine)
)
);