Bitwarden SSH Agent¶
Use the Bitwarden desktop app as your SSH agent so private keys never leave the vault.
- Official docs: https://bitwarden.com/help/ssh-agent/
- Requires: Bitwarden desktop >= 2025.1.2, SSH agent enabled in Settings > Enable SSH agent
0. Install Bitwarden Desktop¶
Automated (via this repo)¶
When installBitwarden is enabled during chezmoi init, the ansible bitwarden role automatically installs:
- CLI (bw): via npm on all profiles
- Desktop app: on desktop profiles only (ubuntu_desktop, macos)
- macOS: via Homebrew Cask (brew install --cask bitwarden)
- Ubuntu: via Snap (primary) or .deb download (fallback)
# Enable during chezmoi init (if not already)
chezmoi init --force # Answer "y" to "Install Bitwarden CLI" prompt
# Or run the bitwarden role manually with desktop install
cd ~/.ansible && ansible-playbook playbooks/linux.yml --tags bitwarden --extra-vars "bitwarden_install_desktop=true"
Manual¶
If you prefer to install manually or are on ubuntu_server:
- macOS: brew install --cask bitwarden
- Ubuntu (snap): sudo snap install bitwarden
- Ubuntu (.deb): Download from vault.bitwarden.com
- Flatpak: flatpak install flathub com.bitwarden.desktop
How It Works¶
┌──────────────┐ SSH_AUTH_SOCK ┌───────────────────┐
│ ssh / git │ ───────────────────▶ │ Bitwarden Agent │
│ (any CLI) │ │ (desktop app) │
└──────────────┘ └───────────────────┘
│
▼
Vault (encrypted)
├─ SSH: ssh_key_1
├─ SSH: ssh_key_2
└─ SSH: ssh_key_3
When an SSH client needs a key, it talks to whichever agent SSH_AUTH_SOCK points to.
Bitwarden creates a Unix socket file; pointing SSH_AUTH_SOCK there makes Bitwarden the agent.
The desktop app prompts you to authorize each key usage (configurable under Settings).
1. Import Keys Into Bitwarden¶
Via the desktop app¶
- Open Bitwarden desktop, click New > SSH key.
- Paste your private key (OpenSSH or PKCS#8 format) using Import key from clipboard.
- The public key and fingerprint are derived automatically.
Via the CLI script¶
This repo includes an import script (see import_ssh_to_bw.sh docs):
# Interactive -- pick which keys to import
ssh-to-bitwarden
# Import all keys from ~/.ssh
ssh-to-bitwarden --all
# Preview only
ssh-to-bitwarden --dry-run
2. Configure SSH_AUTH_SOCK¶
The socket path depends on how Bitwarden was installed:
| Installation | macOS socket path | Linux socket path |
|---|---|---|
.dmg |
~/.bitwarden-ssh-agent.sock |
-- |
| Mac App Store | ~/Library/Containers/com.bitwarden.desktop/Data/.bitwarden-ssh-agent.sock |
-- |
| Native / .deb | -- | ~/.bitwarden-ssh-agent.sock |
| Snap | -- | ~/snap/bitwarden/current/.bitwarden-ssh-agent.sock |
| Flatpak | -- | ~/.var/app/com.bitwarden.desktop/data/.bitwarden-ssh-agent.sock |
This repo auto-detects the socket in ~/.config/zsh/tools/94_ssh_agent.zsh.
It tries each candidate path in order and exports SSH_AUTH_SOCK for the first socket found and responding.
No manual shell configuration is needed if you use the managed zsh config.
Automatic Fallback¶
If Bitwarden desktop is not running (or its socket is stale), the agent script
automatically falls back to a persistent ssh-agent and loads keys from ~/.ssh/.
See SSH Agent Fallback for full details on the fallback chain.
3. Verify¶
# List keys the agent knows about
ssh-add -l
# Expected output (example):
# 3072 SHA256:S93TIv0W2E1B... SSH: ssh_key_1 (RSA)
# 3072 SHA256:B7ZcVqELH0RQ... SSH: ssh_key_2 (RSA)
# 3072 SHA256:i+mZs1/NiKo+... SSH: ssh_key_3 (RSA)
# Test GitHub authentication
ssh -T git@github.com
# Hi daviddwlee84! You've successfully authenticated, ...
If ssh-add -l returns "The agent has no identities", check:
- Bitwarden desktop is running and unlocked.
- SSH agent is enabled in Bitwarden Settings.
SSH_AUTH_SOCKpoints to the correct socket (echo $SSH_AUTH_SOCK).
4. Interaction With ~/.ssh/config¶
How SSH selects keys¶
SSH tries keys in this order:
- Keys specified by
IdentityFilein~/.ssh/config(read directly from disk). - Keys offered by the agent (
SSH_AUTH_SOCK).
This means with Bitwarden as the agent, both sources work together:
- If
IdentityFile ~/.ssh/jingleexists on disk, SSH uses it directly (no agent involved). - If the file is missing or its key is rejected, SSH falls back to keys from the Bitwarden agent.
Recommended config patterns¶
Keep IdentityFile (local file primary, Bitwarden fallback)¶
This is the safest migration path. Your existing config works unchanged. If you ever delete local key files, Bitwarden agent seamlessly takes over:
# ~/.ssh/config
Host github.com
HostName github.com
IdentityFile ~/.ssh/jingle # used if file exists on disk
# Bitwarden agent is fallback
Host azure
HostName <vm>.<region>.cloudapp.azure.com
User daviddwlee84
Port 22
IdentityFile ~/.ssh/YetAnotherStupidVM
Agent-only (no local key files needed)¶
If you want to fully rely on Bitwarden and remove private keys from disk:
# ~/.ssh/config
Host github.com
HostName github.com
# No IdentityFile -- agent provides the right key automatically
Host azure
HostName <vm>.<region>.cloudapp.azure.com
User daviddwlee84
Port 22
# No IdentityFile -- agent provides the right key automatically
SSH tries each key from the agent until the server accepts one.
Pinning a specific key via fingerprint (agent-only, explicit)¶
If you have many keys in the agent and want to avoid trial-and-error,
use IdentityFile with the key's public key file (.pub files can remain on disk safely):
With IdentitiesOnly yes, SSH will only request the matching key from the agent
(identified by the public key) and won't try others. This is useful when servers
limit authentication attempts.
What to avoid¶
# DON'T combine IdentitiesOnly with no IdentityFile when using an agent
Host example
IdentitiesOnly yes
# No IdentityFile = no keys will be tried at all!
IdentitiesOnly yes without an IdentityFile disables agent key offering entirely.
5. Git Commit Signing With SSH¶
Bitwarden SSH keys can also sign Git commits:
# Configure Git to use SSH signing
git config --global gpg.format ssh
git config --global user.signingkey "ssh-rsa AAAAB3Nza..." # your public key
git config --global commit.gpgsign true
On GitHub, add the same public key as a Signing Key (separate from the Authentication Key) under Settings > SSH and GPG keys.
6. SSH Agent Forwarding¶
Use -A to forward the Bitwarden agent to a remote host:
Or in ~/.ssh/config:
The remote host can then use your Bitwarden-managed keys to authenticate onward
(e.g., git pull on the remote server) without your private keys ever leaving your machine.
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
ssh-add -l returns "no identities" |
Bitwarden locked or agent disabled | Unlock Bitwarden, enable SSH agent in Settings |
ssh-add -l returns "connection refused" |
Wrong socket path | Check echo $SSH_AUTH_SOCK and ls -la the path |
| SSH uses wrong key / too many auth failures | Too many agent keys tried before the right one | Add IdentityFile with .pub and IdentitiesOnly yes |
| Git commit signing fails | user.signingkey not set or wrong |
Verify with git config --global user.signingkey |
| Agent works in terminal but not in IDE | IDE uses its own environment | Configure SSH_AUTH_SOCK in IDE settings or launch IDE from terminal |
| Bitwarden closed but SSH still works | Fallback ssh-agent took over (expected) | See SSH Agent Fallback |
git push/ssh fails Connection closed by … port 443 + Could not read from remote repository on a remote/headless session; intermittent (first use OK, later fail) |
The desktop "Confirm SSH key usage" prompt renders on the box's physical display, which you can't click over SSH/tmux, so the agent refuses to sign (approval is cached briefly → first use works, then fails) | Approve at the physical screen; or disable per-use confirmation in Settings → SSH agent; or forward the agent from a clickable machine (ssh -A); or use HTTPS+PAT for git. Full write-up: pitfalls/bitwarden-ssh-agent-confirm-blocks-remote-git-push.md |
Related¶
- SSH Agent Fallback -- Fallback chain: Bitwarden → existing agent → ssh-agent
- Bitwarden SSH Agent official docs
- import_ssh_to_bw.sh -- Bulk import SSH keys to Bitwarden
~/.config/zsh/tools/94_ssh_agent.zsh-- SSH agent auto-detection and fallback~/.config/zsh/tools/95_bitwarden.zsh-- Bitwarden CLI zsh completion