Your SSH key is a file. ~/.ssh/id_ed25519 — 119 bytes of plaintext sitting on disk. Back up your home directory, or get code execution on your machine, and someone has it. Every server you have access to is now available to them.
Hardware tokens solve this. YubiKey, for example, stores the key in a chip and requires physical presence for every signature. But YubiKey requires USB, or a specific driver, or a PIN you have to remember. It doesn't work across machines without carrying the dongle.
Gong's approach is different. The key is never stored anywhere complete. It's split across two physical devices — your phone and your Gong key carrier. Any signature requires both to cooperate. Copying your disk gets you nothing. Stealing your carrier gets you nothing. Both must be physically present.
How It Works
When you enrolled on Gong, a P-256 keypair was generated. The private key was immediately split using Shamir's Secret Sharing into three shares: one in your iPhone's Secure Enclave, one in your Gong key carrier, one held locally. Any two of three reconstruct the key. One alone is useless.
The enrolled P-256 public key is also a valid SSH key. OpenSSH calls the format ecdsa-sha2-nistp256 — same key, same curve, same signature algorithm. The Gong SSH agent serves it over a Unix socket (SSH_AUTH_SOCK), exactly the interface every SSH client expects. No special client software required.
When you SSH to a server, the agent receives the sign request. Your carrier's LED flashes. Press the button. The BLE ceremony completes in about two seconds. SSH auth succeeds.
Prerequisites
- Gong enrollment complete (identity split across your devices)
- Gong key carrier (the physical device — ships separately)
- Python 3.10+ with the
cryptographypackage on the machine running the agent
Step 1 — Install the Agent
curl -fsSL https://gong.com/install/gong-ssh-agent -o ~/.local/bin/gong-ssh-agent
chmod +x ~/.local/bin/gong-ssh-agentOr from source:
# The agent is in the gong-auth repo
cp gong-auth/scripts/gong-ssh-agent ~/.local/bin/
chmod +x ~/.local/bin/gong-ssh-agentInstall the Python dependency if not already present:
pip install cryptographyStep 2 — Start the Agent
gong-ssh-agent &The agent reads your local share files, reconstructs the signing key in memory, opens a socket at ~/.gong/agent.sock, and starts listening. The master key bytes are wiped immediately after the P-256 signing key is derived. Only the derived key lives in memory.
Tell your shell to use it:
eval $(gong-ssh-agent --print-env)To make this permanent, add to ~/.bashrc or ~/.zshrc:
export SSH_AUTH_SOCK="$HOME/.gong/agent.sock"Verify it is running:
ssh-add -l
# 256 SHA256:gJQ0SqNxXM4llCMQ3DOBzg82uLBaFbzedKJ6jMuFtbs gong-ssh-agent (ECDSA)Step 3 — Get Your Public Key
gong-ssh-agent --print-pubkeyOutput:
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBN... gong-keyThis is a standard OpenSSH public key in authorized_keys format. The fingerprint matches what ssh-add -l shows. You can verify they correspond before deploying.
Step 4 — Deploy to Servers
Any Linux server:
gong-ssh-agent --print-pubkey | ssh user@server "cat >> ~/.ssh/authorized_keys"GitHub — Settings → SSH and GPG keys → New SSH key. Paste the --print-pubkey output. Label it "Gong key".
GitLab, Bitbucket, SourceHut — same: account SSH settings, paste the key.
Multiple servers at once:
PUBKEY=$(gong-ssh-agent --print-pubkey)
for host in server1 server2 server3; do
ssh user@$host "echo '$PUBKEY' >> ~/.ssh/authorized_keys"
doneThe public key never changes unless you re-enroll. Add it once and it works for the lifetime of your identity.
Step 5 — Test Auth
ssh user@your-serverWatch your carrier. The LED flashes when a sign request arrives. Press the button. The connection establishes.
If the carrier is not nearby or the button is not pressed within ten seconds, the agent returns failure and SSH reports permission denied. This is by design.
For git:
git clone git@github.com:your-org/your-repo
# carrier LED flashes → press button → clone proceedsStep 6 — Auto-Start
To start the agent automatically at login:
mkdir -p ~/.config/systemd/user
cat > ~/.config/systemd/user/gong-ssh-agent.service << 'EOF'
[Unit]
Description=Gong SSH Agent
[Service]
Type=simple
ExecStart=%h/.local/bin/gong-ssh-agent
Restart=on-failure
[Install]
WantedBy=default.target
EOF
systemctl --user enable --now gong-ssh-agentCheck status:
systemctl --user status gong-ssh-agentAudit Log
Every sign request is logged to ~/.gong/agent.log in append-only format:
2026-05-22T14:32:01 STARTED key=ecdsa-sha2-nistp256 fingerprint=SHA256:gJQ0...
2026-05-22T14:32:15 SIGN_REQUEST preview=4a3f1c... APPROVED
2026-05-22T14:32:15 SIGN_OK count=1 fingerprint=SHA256:gJQ0...You have a complete record of every machine that used your key and when. The log does not contain the signed data — only a short preview for identification.
The Key Carrier
The carrier is a small device on your keychain. It holds one Shamir share of your master key, protected inside the nRF54L15 hardware crypto accelerator. The share never leaves the chip in plaintext.
The authentication flow takes about two seconds end to end:
1. SSH sends the sign request to the agent
2. Agent triggers the ceremony — your phone shows "SSH login — approve?"
3. Carrier LED flashes
4. You press the button
5. BLE exchange completes, signature returned
6. SSH reports authenticated
No carrier within BLE range, no auth. Carrier present but button not pressed within the timeout, no auth. Both conditions must be satisfied.
This is what hardware auth should feel like: invisible until you need it, unambiguous when you do.
Key Lifecycle
Your public key is stable. Adding it to a server once means it works for the lifetime of your identity. If you replace your phone, your carrier, or your laptop, the reconstruction ceremony produces the same key from any two surviving shares.
Remove a lost device from the enrollment set — the public key stays the same, every server you've added it to continues to work, and the lost device's share is no longer sufficient to reconstruct anything.
Same key for SSH. Same key for git commit signing. Same key for gong.com login. One enrollment covers all of it.