SSH-TPM-AGENT(1)

πŸ“¦
version 0.9.0 Β· 4 versions
, in arch rolling

SSH-TPM-AGENT(1) β€” the ssh-tpm-agent manual, but make it make sense πŸ’…

okay bestie, so this is the ssh-tpm-agent manual page, and no cap it's actually kind of iconic. grab a snack, we're going through every single flag, every example, every file β€” all of it. nothing skipped, periodt. 🫢


✨ NAME ✨

ssh-tpm-agent β€” it's an ssh-agent, but for TPM 2.0 keys. it exists so you can have wrapped private keys doing your public key authentication for you. king behaviour.


✨ SYNOPSIS ✨

ssh-tpm-agent [OPTIONS]

ssh-tpm-agent --print-socket

ssh-tpm-agent --install-user-units

✨ DESCRIPTION ✨

so ssh-tpm-agent is a program that creates keys using a Trusted Platform Module (TPM), which is the whole vibe: it enables wrapped private keys so you can do public key authentication. that's the plot. πŸ’–


✨ OPTIONS ✨

  • -l PATH β€” the path of the UNIX socket to open. defaults to $XDG_RUNTIME_DIR/ssh-tpm-agent.sock if you don't say anything, bestie.
  • -A PATH β€” fallback ssh-agent sockets so extra keys can be looked up. basically "hey, also check over there."
  • --print-socket β€” prints the socket to STDIN. yes, STDIN, that's what it says, we don't question it.
  • --key-dir PATH β€” the path of the directory to go looking for TPM sealed keys in. defaults to ~/.ssh.
  • --no-load β€” do not load TPM sealed keys from ~/.ssh by default. lowkey a boundaries thing.
  • -o, --owner-password β€” asks for the owner password.
  • --no-cache β€” the agent will not cache key passwords. it's giving "i don't remember your secrets and honestly that's healthy."
  • --hierarchy HIERARCHY β€” preload hierarchy keys into the agent. see Hierarchy Keys below for the whole tea. available hierarchies:
    • owner, o
    • endorsement, e
    • null, n
    • platform, p
  • -d β€” enable debug logging. your verbose era.
  • --install-user-units β€” installs systemd system units and sshd configs so ssh-tpm-agent can be used as a hostkey agent.
  • --swtpm β€” stores keys inside a swtpm instance instead of the actual TPM.
🚨 bestie this is not a security feature and your keys are not stored securely. do not do this in prod, i'm serious. 😭

can also be turned on with the environment variable SSH_TPM_AGENT_SWTPM.


🌸 EXAMPLES 🌸

🌈 Normal agent usage

ssh-tpm-agent can be used as a drop-in replacement to ssh-agent, and it works the same way. exactly the same way. no new muscle memory needed, slay.

$ ssh-tpm-keygen
# Add ~/.ssh/id_ecdsa.pub to your Github accounts
$ ssh-tpm-agent &
$ export SSH_AUTH_SOCK=$(ssh-tpm-agent --print-socket)
$ ssh git@github.com

peep ssh-tpm-keygen(1) for keygen usage, iykyk.

🌈 Agent fallback support

ssh-tpm-agent supports fallback to different ssh-agents. you add agents with the -A switch, and that causes ssh-tpm-agent to fan-out to all available agents looking for keys.

this is so practical if you have multiple keys from different agent implementations but you only want to rely on one socket. one socket, many keys, main character energy.

# Start the usual ssh-agent
$ eval $(ssh-agent)

# Create a strong RSA key
$ ssh-keygen -t rsa -b 4096 -f id_rsa -C ssh-agent
...
The key fingerprint is:
SHA256:zLSeyU/6NKHGEvyZLA866S1jGqwdwdAxRFff8Z2N1i0 ssh-agent

$ ssh-add id_rsa
Identity added: id_rsa (ssh-agent)

# Print looonnggg key
$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc[...]8TWynQ== ssh-agent

# Create key on the TPM
$ ssh-tpm-keygen -C ssh-tpm-agent
Generating a sealed public/private ecdsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_ecdsa):
Enter passphrase (empty for no passphrase):
Confirm passphrase:
Your identification has been saved in /home/user/.ssh/id_ecdsa.tpm
Your public key has been saved in /home/user/.ssh/id_ecdsa.pub
The key fingerprint is:
SHA256:PoQyuzOpEBLqT+xtP0dnvyBVL6UQTiQeCWN/EXIxPOo
The key's randomart image is the color of television, tuned to a dead channel.

# Start ssh-tpm-agent with a proxy socket
$ ssh-tpm-agent -A "${SSH_AUTH_SOCK}" &

$ export SSH_AUTH_SOCK="$(ssh-tpm-agent --print-socket)"

# ssh-tpm-agent is proxying the keys from ssh-agent
$ ssh-add -L
ssh-rsa AAAAB3NzaC1yc[...]8TWynQ== ssh-agent
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNo[...]q4whro= ssh-tpm-agent

look at that. proxying keys from ssh-agent like it's nothing. πŸ’…

🌈 Hostkeys usage

ssh-tpm-agent can also be used to serve host keys for an ssh server. ssh-tpm-hostkeys has convenient flags to help install systemd configurations and services to the system. this will create a system socket for ssh-tpm-agent under /var/tmp/ssh-tpm-agent.sock.

$ sudo ssh-tpm-keygen -A
2023/09/03 17:03:08 INFO Generating new ECDSA host key
2023/09/03 17:03:08 INFO Wrote /etc/ssh/ssh_tpm_host_ecdsa_key.tpm
2023/09/03 17:03:08 INFO Generating new RSA host key
2023/09/03 17:03:15 INFO Wrote /etc/ssh/ssh_tpm_host_rsa_key.tpm

$ sudo ssh-tpm-hostkeys --install-system-units
Installed /usr/lib/systemd/system/ssh-tpm-agent.service
Installed /usr/lib/systemd/system/ssh-tpm-agent.socket
Installed /usr/lib/systemd/system/ssh-tpm-genkeys.service
Enable with: systemctl enable --now ssh-tpm-agent.socket

$ sudo ssh-tpm-hostkeys --install-sshd-config
Installed /etc/ssh/sshd_config.d/10-ssh-tpm-agent.conf
Restart sshd: systemd restart sshd

$ systemctl enable --now ssh-tpm-agent.socket
$ systemd restart sshd

$ sudo ssh-tpm-hostkeys
ecdsa-sha2-nistp256 AAAAE2V[...]YNwqWY0= root@localhost
ssh-rsa AAAAB3NzaC1ycA[...]N1Jg3fLQKSe7f root@localhost

$ ssh-keyscan -t ecdsa localhost
# localhost:22 SSH-2.0-OpenSSH_9.4
localhost ecdsa-sha2-nistp256 AAAAE2V[...]YNwqWY0=

alternatively, you can totally omit the embedded install flags and just drop in a drop-in configuration for sshd under /etc/ssh/sshd_config.d with this content:

HostKeyAgent /var/tmp/ssh-tpm-agent.sock
HostKey /etc/ssh/ssh_tpm_host_ecdsa_key.pub
HostKey /etc/ssh/ssh_tpm_host_rsa_key.pub

🌈 Hierarchy keys

TPMs are capable of creating static keys utilizing the top-level hierarchies. this lets the user create keys that are available for the lifetime of the device, for the current owner of the device, or for the current session of the device. these keys do not leave the TPM β€” just like other keys created by ssh-tpm-keygen β€” and can always be recreated. always. πŸ’–

these keys can be preloaded into ssh-tpm-agent:

$ ssh-tpm-agent --hierarchy owner &
$ export SSH_AUTH_SOCK="$(ssh-tpm-agent --print-socket)"
$ ssh-add -l
2048 SHA256:yt7A20tcRnzgaD2ATgAXSNWy9sP6wznysp3SkoK3Gj8 Owner hierarchy key (RSA)
256 SHA256:PmEsMeh/DwFP04iUaWLNeX4maMR6r1vfqw1BbbdFjIg Owner hierarchy key (ECDSA)

for usage with sshd, the public part of these keys can be created by combining -A with --hierarchy:

$ ssh-tpm-keygen -A --hierarchy owner
2025/03/10 21:57:08 INFO Generating new hierarcy host key algorithm=RSA hierarchy=owner
2025/03/10 21:57:10 INFO Wrote public key filename=/etc/ssh/ssh_tpm_host_rsa_key.pub
2025/03/10 21:57:10 INFO Generating new hierarcy host key algorithm=ECDSA hierarchy=owner
2025/03/10 21:57:10 INFO Wrote public key filename=/etc/ssh/ssh_tpm_host_ecdsa_key.pub

these files can be used with HostKey as normal in ssh_config.

the different key hierarchies have different properties and lifetimes, so let's go through them πŸ¦‹

  • endorsement hierarchy stores keys created for the lifetime of the device. this hierarchy should not change during the lifetime of the device.
  • owner hierarchy stores keys created for the device owner. these keys will be rotated when tpm2_clear(1) is issued on the platform, which should be done when the device gets a new owner.
  • null hierarchy stores keys created for the current session. the session should be a power cycle of the devices.
⚠️ Note: this feature is experimental. ssh-tpm-agent keeps the TPM objects loaded while running. some TPM devices run out of memory if you attempt to use the hierarchy keys with the usual keys created by ssh-tpm-keygen. 😭 be careful bestie.

✨ ENVIRONMENT ✨

  • SSH_TPM_AUTH_SOCK β€” identifies the path of a unix-domain socket for communication with the agent. defaults to /var/tmp/ssh-tpm-agent.sock.
  • SSH_ASKPASS β€” if ssh-tpm-agent, and other binaries, needs to read a password, it will default to using the terminal if it can. if there's no terminal available, it falls back to calling the binary SSH_ASKPASS points at. see ssh(1) under ENVIRONMENT for more info.
  • SSH_ASKPASS_REQUIRE β€” lets you control the use of the askpass program. valid values are:
    • never β€” ensures ssh will never try to use the askpass program.
    • prefer β€” will prefer to use the askpass program.
    • force β€” will ensure all passphrase inputs will be using the askpass program.

see ssh(1) under ENVIRONMENT for more info.

  • SSH_TPM_AGENT_SWTPM β€” specify if ssh-tpm-agent should use the swtpm backend or not. accepts any non-empty value as true.
  • SSH_TPM_LANDLOCK β€” if set, then ssh-tpm-agent, and the other binaries, will enforce the landlock sandbox where applicable. disabled by default. see landlock(7) for more information.

πŸŽ€ FILES πŸŽ€

  • ~/ssh/id_rsa.tpm, ~/ssh/id_ecdsa.tpm β€” these contain the ssh private keys used by ssh-tpm-agent. they're TPM 2.0 TSS key files, securely wrapped by the TPM. they can be shared publicly since they can only be used by the TPM they were created on β€” but honestly it's probably better to not do that. πŸ™ˆ
  • ~/ssh/id_rsa.pub, ~/ssh/id_ecdsa.pub β€” these contain the ssh public keys. these can be shared publicly, and they're the same format as the ones created by ssh-keygen(1). go off.
  • /run/user/$UID/ssh-tpm-agent.sock β€” the default user ssh-tpm-agent UNIX socket path. used by individual users.
  • /var/tmp/ssh-tpm-agent.sock β€” the default system ssh-tpm-agent UNIX socket path. used for host keys and the system.

πŸ’œ SEE ALSO πŸ’œ

ssh-agent(1), ssh(1), ssh-tpm-keygen(1), ssh-keygen(1)


⭐ NOTES, STANDARDS AND OTHER ⭐


aaand that's the whole page, bestie, you ate it up πŸ“ this was ssh-tpm-agent v0.9.0, dated 2026-08-10 β€” go forth and let your keys live safely inside the TPM, mwah πŸ’‹πŸ§šπŸ’–

πŸ“¦ where this page comes from