
Hermetic is a drop-in replacement for ssh-keygen that uses TPM 2.0 for key storage.
Private keys are generated inside the TPM and never exposed to the OS — not on disk, not in memory.
┌──────────────────────┐
│ H E R M E T I C │
│ sealed by hardware │
└──────────────────────┘
Usage: hermetic <command> [flags]
Commands:
keygen Generate a new TPM-backed ECDSA P-256 SSH key pair
agent Start the SSH agent (serves via Unix socket)
list List stored keys with fingerprints
show Print the public key for a stored key
remove Remove a stored key
doctor Check system prerequisites and TPM readiness
use Configure Git to use a Hermetic key for commit signing
sign Sign a buffer (compatible with ssh-keygen -Y sign)
version Print the version
Getting started:
hermetic doctor Check that your system is ready
hermetic keygen -f mykey -C "me" Generate a new key
hermetic use -f mykey Enable signing with this key
hermetic agent Start the SSH agent
Examples:
# Generate a key and add it to GitHub
hermetic keygen -f github -C "user@host"
hermetic show -f github # copy output to GitHub SSH keys
# Start the SSH agent and use it for SSH
eval $(hermetic agent -s)
ssh -T git@github.com # verify your key works
Use hermetic <command> -h for command-specific help and examples.
Quick Start
1. Install
go install codeberg.org/slowhorse/hermetic/cmd/hermetic@latest
2. Check TPM access
hermetic doctor
Reports TPM availability, device permissions, and Git configuration. Prints actionable hints for any failures.
3. Generate a key
hermetic keygen -f github -C "me@example.com"
Writes an encrypted key blob and a plain SSH public key to $XDG_DATA_HOME/hermetic/keys/ (defaults to ~/.local/share/hermetic/keys/).
4. Add the public key to GitHub / GitLab
hermetic show -f github
Copy the output to your provider's SSH key settings.
5. Start the agent
eval $(hermetic agent -s)
This starts the agent in the background and sets SSH_AUTH_SOCK to the stable XDG_RUNTIME_DIR (e.g., /run/user/1000/hermetic/agent.sock). Add this line to ~/.bashrc or ~/.zshrc to ensure the agent is available in every session.
The agent automatically picks up new or removed keys without a restart when managed through the CLI.
6. Test the connection
ssh -T git@github.com
7. Git commit signing (optional)
hermetic use -f github
Sets gpg.format, user.signingkey, and commit.gpgsign in your global Git config. Pass --local to scope it to the current repository.
How it works
Keys are generated using the TPM's internal RNG and never leave the chip unencrypted. What gets written to $XDG_DATA_HOME/hermetic/keys/ is an encrypted blob that only your specific TPM can unseal.
The Storage Root Key (SRK) is derived deterministically, so Hermetic doesn't consume persistent TPM slots.
Signing requests go through the SSH agent, which passes them to the TPM. The agent holds no key material itself.
Threat Model & Limitations
Hardware Security
- Key Extraction: Private keys are generated inside the TPM and are marked as non-exportable. They cannot be extracted from the hardware, even by a compromised OS or an attacker with physical access to the disk.
- Device Binding: Keys are cryptographically bound to the specific TPM that created them. Moving the key blobs to another machine will not work.
Access Control
- No Passphrases (Current): Hermetic currently does not support TPM-enforced passphrases or PINs. If an attacker gains access to your logged-in session, they can use the SSH agent to sign requests.
- OS Permissions: Protection against unauthorized use of the keys relies on standard OS file and socket permissions.
Recovery & Persistence
- No Backups: Because keys never leave the TPM, they cannot be backed up. If your TPM is cleared or the hardware fails, you will lose access to the keys and must generate new ones.
- SRK Stability: Hermetic uses a deterministic Storage Root Key (SRK). If your TPM's owner hierarchy is cleared/reset, the SRK seed may change, rendering existing key blobs unreadable.
| Platform |
TPM interface |
| Linux |
/dev/tpmrm0 (kernel resource manager) |
| Windows |
TBS (TPM Base Services) |
| MacOS |
swtpm via Unix socket or TCP |
| Testing |
swtpm via Unix socket or TCP |
Custom TPM path
Override the default device with HERMETIC_TPM_PATH:
# Hardware device
export HERMETIC_TPM_PATH=/dev/tpmrm0
# Software TPM (Unix socket)
export HERMETIC_TPM_PATH=/tmp/swtpm.sock
# Software TPM (TCP)
export HERMETIC_TPM_PATH=tcp://127.0.0.1:2321