Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions nix/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,7 @@
./home/common.nix
./home/linux.nix
./home/hyprland.nix # Hyprland rice (nixos-laptop only)
./home/ssh-tpm-agent.nix # TPM-sealed SSH key (nixos-laptop only: WSL has no TPM)
./home/dev.nix # dev environment such as direnv
./home/restic-backup-linux.nix # restic (systemd user timer)
sops-nix.homeManagerModules.sops
Expand Down Expand Up @@ -718,6 +719,7 @@
./home/linux.nix
./home/hyprland.nix
./home/dev.nix
./home/ssh-tpm-agent.nix
./home/workstation.nix
];
}
Expand Down
23 changes: 23 additions & 0 deletions nix/home/ssh-tpm-agent.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{ lib, ... }:
{
# TPM-sealed SSH key for the laptop (nixos-laptop only).
#
# This is the Linux counterpart of the Mac's Secure Enclave key: ssh-tpm-keygen creates the key
# inside the TPM and it cannot be extracted, so losing the machine does not leak a usable key.
# It matters most here — the laptop leaves the house, and it is the client that carries the
# longest-lived SSH certificate (it cannot renew its own; only the Mac can sign).
#
# Not on WSL despite sharing home/linux.nix: no TPM there.
# Not a substitute for the LUKS TPM+PIN slot in hosts/nixos-laptop.nix — different key, different
# purpose. Note fprintd (sudo / hyprlock) does not gate this: on Linux a fingerprint authenticates
# a session via PAM, it is not a policy the TPM can attach to a key. The available binding is a
# PIN on the key itself, which is what ssh-tpm-keygen offers.
services.ssh-tpm-agent.enable = true;

# home-manager's sshAuthSock.initialization only defines bash / fish / nushell (see
# modules/misc/ssh-auth-sock.nix), so a zsh login gets no SSH_AUTH_SOCK and ssh would fall
# through to whatever ~/.ssh/config names. Export it here instead of patching upstream.
programs.zsh.initContent = lib.mkOrder 550 ''
export SSH_AUTH_SOCK="''${XDG_RUNTIME_DIR:-/run/user/$UID}/ssh-tpm-agent.sock"
'';
}
8 changes: 8 additions & 0 deletions nix/hosts/nixos-laptop.nix
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
config,
pkgs,
lib,
user,
Expand Down Expand Up @@ -54,6 +55,10 @@
# the key to an untampered boot chain, not to a person: whoever powers the laptop on gets a
# decrypted disk. The TPM rate-limits PIN attempts in hardware, so a short PIN is enough — this is
# not a passphrase, and brute force is not on the table.
# userspace TPM access (tpm2-tss + udev rules + the tss group). The LUKS slot above does not
# need this — that runs in initrd as root — but ssh-tpm-agent talks to the TPM as the user.
security.tpm2.enable = true;

# tpm2-pin must match how the slot was enrolled; enrolling without --tpm2-with-pin and setting this
# (or the reverse) just falls through to the passphrase prompt.
boot.initrd.luks.devices.cryptroot.crypttabExtraOpts = [
Expand Down Expand Up @@ -237,6 +242,9 @@
"wheel"
"networkmanager"
"video"
# Talking to /dev/tpmrm0 needs the tss group. Required by home/ssh-tpm-agent.nix, which
# asserts on this rather than failing at runtime with a permission error.
config.security.tpm2.tssGroup
];
shell = pkgs.zsh;
};
Expand Down
Loading
Loading