ssh.nix (3066B)
1 # modules/home/ssh.nix — the SSH key and client config, from the flake. 2 # 3 # The private key is a sops secret (secrets/secrets.yaml: ssh_id_ed25519; 4 # `nix-cheat secrets`). At login sops-nix decrypts it with the age key into 5 # the runtime secrets dir and ~/.config/sops-nix/secrets/ssh_id_ed25519 points 6 # there; ~/.ssh/config names that path, so a fresh machine has a working key 7 # as soon as ~/.config/sops/age/keys.txt is restored. The public half is 8 # plain text in ~/.ssh/id_ed25519.pub (comment daemonsec@nixos; registered on 9 # gitlab.com as "nixos", auth and signing, and glab's git_protocol is ssh). 10 # 11 # A plain copy from before this module may still sit at ~/.ssh/id_ed25519; 12 # nothing reads it any more. 13 # 14 # The agent: services.gnome.gnome-keyring.enable (configuration.nix, and 15 # mkDefault in workstation.nix) makes gcr-ssh-agent the $SSH_AUTH_SOCK 16 # (/run/user/1000/gcr/ssh). It is not gpg-agent and not plain ssh-agent, and 17 # it refuses signing requests when it cannot prompt. ssh prefers an agent that 18 # holds the key over reading the file, so that refusal is fatal even though 19 # the key is readable. Hence IdentityAgent = "none" below, and no 20 # AddKeysToAgent. Verified: with the agent, `ssh -T git@gitlab.com` fails; 21 # with SSH_AUTH_SOCK unset it prints "Welcome to GitLab, @DAEMON-404!". 22 { ... }: 23 { 24 flake.homeModules.ssh = 25 { config, ... }: 26 let 27 key = config.sops.secrets.ssh_id_ed25519.path; 28 in 29 { 30 sops.secrets.ssh_id_ed25519 = { }; # → %r/secrets.d/…, mode 0400 (ssh is happy with that) 31 32 home.file.".ssh/id_ed25519.pub".text = '' 33 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIB8ExB6Gv5T7DwwVeNqVmzbwCcZ/ULuKL2pAXS7zg4NR daemonsec@nixos 34 ''; 35 36 programs.ssh = { 37 enable = true; 38 enableDefaultConfig = false; 39 settings = { 40 "gitlab.com" = { 41 User = "git"; 42 IdentityFile = key; 43 IdentitiesOnly = "yes"; 44 # Read the key from the file, never through an agent. See the note 45 # below: gnome-keyring's gcr-ssh-agent owns $SSH_AUTH_SOCK on this 46 # machine and refuses to sign, which breaks `git push` outright. 47 IdentityAgent = "none"; 48 }; 49 "github.com" = { 50 User = "git"; 51 IdentityFile = key; 52 IdentitiesOnly = "yes"; 53 IdentityAgent = "none"; 54 }; 55 "gitea.com" = { 56 User = "git"; 57 IdentityFile = key; 58 IdentitiesOnly = "yes"; 59 IdentityAgent = "none"; 60 }; 61 "*" = { 62 IdentityFile = key; 63 # NOT AddKeysToAgent = "yes". That is what put this key into 64 # gcr-ssh-agent in the first place, and once the agent holds a key 65 # ssh asks IT to sign rather than using the file — so a refusal from 66 # gcr became `sign_and_send_pubkey: signing failed ... agent refused 67 # operation` followed by `Permission denied (publickey)`, with a 68 # perfectly good key sitting on disk. 69 ServerAliveInterval = 30; 70 HashKnownHosts = "no"; 71 }; 72 }; 73 }; 74 } 75 ; 76 }