Commit 03e1069491f6

Vincent Demeester <vincent@sbr.pm>
2026-01-29 16:38:27
feat(ssh): migrate from PIV to FIDO2 resident keys
- Add FIDO2 SSH keys to globals.nix (homelab + critical-infra) - Configure SSH identity files per host (git providers, redhat, homelab) - Make FIDO2 config conditional on kyushu (has Yubikey attached) - Enable ssh-agent, disable yubikey-agent service - Critical hosts (athena, demeter, kerkouane) use touch-required key Key strategy: - ssh:github, ssh:gitlab, ssh:codeberg, ssh:srht (no-touch) for git - ssh:redhat (no-touch) for work - ssh:homelab (no-touch) for general homelab - ssh:critical-infra (touch-required) for DNS/network infra Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8f244c7
Changed files (4)
dots
.config
home
common
systems
common
hardware
dots/.config/niri/config.kdl
@@ -81,8 +81,8 @@ spawn-at-startup "dbus-update-activation-environment" "--systemd" "--all"
 spawn-at-startup "emacs" "--fg-daemon"
 spawn-at-startup "battery-monitor"
 spawn-at-startup "waybar"
-// FIXME should be through systemd
-spawn-at-startup "yubikey-agent" "-l" "/run/user/1000/yubikey-agent/yubikey-agent.sock"
+// Disabled - using FIDO2 keys with ssh-agent instead of PIV with yubikey-agent
+// spawn-at-startup "yubikey-agent" "-l" "/run/user/1000/yubikey-agent/yubikey-agent.sock"
 spawn-at-startup "swaybg" "-i" "/home/vincent/desktop/pictures/lockscreen"
 
 prefer-no-csd
home/common/shell/openssh.nix
@@ -1,15 +1,21 @@
 {
   pkgs,
+  lib,
   config,
   globals,
   libx,
+  hostname,
   ...
 }:
+let
+  # FIDO2 keys are only available on hosts with Yubikey attached
+  hasFido2Keys = hostname == "kyushu";
+in
 {
   home.packages = with pkgs; [
     sshfs
   ];
-  # services.ssh-agent.enable = true;
+  services.ssh-agent.enable = true;
   programs.ssh = {
     enable = true;
     enableDefaultConfig = false;
@@ -66,6 +72,7 @@
       "github.com" = {
         hostname = "github.com";
         user = "git";
+        identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_github_sk";
         extraOptions = {
           controlMaster = "auto";
           controlPersist = "360";
@@ -74,6 +81,16 @@
       "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";
@@ -82,6 +99,7 @@
       "git.sr.ht" = {
         hostname = "git.sr.ht";
         user = "git";
+        identityFile = lib.mkIf hasFido2Keys "~/.ssh/id_srht_sk";
         extraOptions = {
           controlMaster = "auto";
           controlPersist = "360";
@@ -89,23 +107,39 @@
       };
       "*.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";
-          # identityFile = "~/.ssh/kyushu";
-          # identityAgent = "empty";
         };
       };
       "10.100.0.*" = {
         forwardAgent = true;
-        # identityFile = "~/.ssh/kyushu";
-        # identityAgent = "empty";
+        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 = lib.mkIf hasFido2Keys "~/.ssh/id_critical_infra_sk";
       };
     }
     // libx.sshConfigs globals.machines;
systems/common/hardware/yubikey.nix
@@ -48,7 +48,8 @@
   };
 
   programs.gnupg.agent.pinentryPackage = pkgs.pinentry-gnome3;
-  services.yubikey-agent.enable = true;
+  # Disabled - using FIDO2 keys with ssh-agent instead of PIV with yubikey-agent
+  services.yubikey-agent.enable = false;
   # systemd.packages = [ pkgs.yubikey-agent ];
 
   # This overrides the systemd user unit shipped with the
globals.nix
@@ -1,11 +1,14 @@
 _: {
   ssh = {
     vincent = [
-      # Yubikeys
+      # Yubikeys (PIV - legacy, keep during transition)
       "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFT5Rx+4Wuvd8lMBkcHxb4oHdRhm/OTg+p5tvPzoIN9enSmgRw5Inm/SlS8ZzV87G1NESTgzDRi6hREvqDlKvxs="
       "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGHMa4rHuBbQQYv+8jvlkFCD2VYRGA4+5fnZAhLx8iDirzfEPqHB60UJWcDeixnJCUlpJjzFbS4crNOXhfCTCTE="
       "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBBFzxC16VqwTgWDQfw2YCiOw2JzpH3z9XgHtKoHhBdHi2i9m9XUc7fIUeEIIf7P8ARRNd8q5bjvl8JY7LtPkNCU="
-      # AOMI (only "trusted" one)
+      # FIDO2 resident keys (homelab)
+      "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIODTc5Exm59skgJdu6/rA3CpX4k4P1CFBqCFtelWGGmEAAAAC3NzaDpob21lbGFi homelab-servers"
+      "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIAGh5p44LvQrWjAMyC/5LjUnViqFl3ddVfiFnoiLgJb7AAAAEnNzaDpjcml0aWNhbC1pbmZyYQ== infra-touch-required"
+      # Host keys (trusted machines)
       "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILJmTdMKYdgqpbQWBif58VBuwX+GqMGsMfB1ey1TKrM3 vincent@aomi"
       "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGThdcaPfIaB7d+K5uODqEusLKGI5ZCye0aNOCaMoInO Kyushu's ssh key"
     ];