How to NOT store private keys on your computer.

I used my Trezor Model T to validate that the following guide is working correctly. However, it should also be possible with Ledger or KeepKey.


If you run into any kind of problem, follow these instructions or look for existing issues, solved or not.

brew install libusb
brew install trezor-agent

Wait a second… Roman Zeyde, who is that guy? Why should you install software you don’t know anything about? Calm down, he is endorsed by TREZOR. Nevertheless, you should have a look at the source code yourself. Don’t trust, verify.


After the successful installation of the trezor-agent, we can start using it. This is how to create a new public key for each {user}@{host} combination and then saving it all in ~/.ssh/trezor.conf like this:

trezor-agent -e ed25519 {user}@{host} >> ~/.ssh/trezor.conf

In public-key cryptographyEdwards-curve Digital Signature Algorithm (EdDSA) is a digital signature scheme using a variant of Schnorr signature based on twisted Edwards curves.[1] It is designed to be faster than existing digital signature schemes without sacrificing security.

Launchd Agent for macOS

We are going to run trezor-agent every time ssh connects to the specified UNIX-domain socket. The socket can be specified in the ~/.ssh/config file with an option called IdentityAgent. This option specifies the UNIX-domain socket used to communicate with the authentication agent.

This option allows us to use the hardware wallet for some hosts, but not for others with minimal effort.

Host dev
    User john
    IdentityAgent ~/.ssh/trezor-agent/S.ssh

The previously created ~/.ssh/trezor.conf will be used as the identity argument for trezor-agent.

identity can be a path (starting with /) to a file containing a list of public keys generated by Trezor. I.e. /home/myUser/.ssh/trezor.conf with one public key per line.

System-wide configuration with Launchd

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" ""&gt;
<plist version="1.0">
<string>Trezor SSH Socket</string>
<string>ln -s -f $SSH_TREZOR_SOCK ~/.ssh/trezor-agent/S.ssh &amp;&amp; /usr/local/bin/trezor-agent –foreground –sock-path $SSH_TREZOR_SOCK ~/.ssh/trezor.conf 2&gt; ~/.ssh/trezor-agent/error.log</string>
Example of a working launchd configuration.

Whoaaa. What’s happening here? The interesting bit is what’s happening each time ssh connects to the socket specified in the ssh config:

ln -s -f $SSH_TREZOR_SOCK ~/.ssh/trezor-agent/S.ssh
/usr/local/bin/trezor-agent --foreground --sock-path $SSH_TREZOR_SOCK ~/.ssh/trezor.conf 2> ~/.ssh/trezor-agent/error.log

  1. We symlink the socket created by our launchd command to make the handling a little bit easier.
  2. We run the trezor-agent and point it to the unix domain socket.

You can now login as usual, except you have to confirm the log in via your Hardware Wallet. Congratulations.

There are several other ways how the trezor-agent can be used for SSH. Also have a look at the GPG instructions. Thanks a lot to Roman Zeyde for creating and maintaining trezor-agent.

Photo by James Sutton on Unsplash

1 Comment

  1. Note to self:

    In case the daemon crashes for whatever reason:

    ❯ cd ~/Library/LaunchAgents
    ❯ launchctl unload trezor.ssh.socket.plist
    ❯ launchctl load trezor.ssh.socket.plist
    ❯ launchctl start trezor.ssh.socket.plist

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.