~/.ssh/ when applying dotfiles. This ensures your private keys never touch your git repository.
Overview
SSH key management in this setup:- Private keys stored as Bitwarden Secure Notes
- Public keys stored as Bitwarden Custom Fields
- Keys pulled via chezmoi templates during
chezmoi apply - Proper file permissions set automatically
Storage in Bitwarden
Creating SSH Key Item
-
Generate SSH key pair (if new):
-
Create Bitwarden item:
- Item type: Secure Note
- Name:
yurgenlira ssh key - Notes: Paste contents of private key (
~/.ssh/yurgenlira) - Custom field:
public_key= contents of public key (~/.ssh/yurgenlira.pub)
Chezmoi Templates
SSH keys are provisioned using Bitwarden template functions:Private Key Template
private_dot_ssh/private_yurgenlira.tmpl:1
private_prefix - Sets file permissions to 600 (owner read/write only)dot_ssh- Creates.sshdirectoryyurgenlira.tmpl- Target filenameyurgenliraafter template processing
Public Key Template
private_dot_ssh/private_yurgenlira.pub.tmpl:1-2
private_prefix - Sets directory permissions appropriatelyyurgenlira.pub.tmpl- Target filenameyurgenlira.pub
SSH Config (Encrypted)
The SSH config file is encrypted with age:- Store host configurations securely in git
- Define aliases and connection settings
- Keep infrastructure details private
Security Table
From the README:| Secret | Storage | How it’s used |
|---|---|---|
| SSH private key | Bitwarden Secure Note | Pulled via bitwarden template function |
| AWS credentials | Bitwarden Custom Fields | Pulled via bitwardenFields template function |
age private key | Bitwarden Secure Note | Retrieved during bootstrap, stored at ~/.config/chezmoi/key.txt |
| Encrypted files | Git repo (.age) | Decrypted by chezmoi using the age identity |
Applying SSH Keys
When you runchezmoi apply:
- Chezmoi reads Bitwarden templates
- Calls
bw get item "yurgenlira ssh key" - Extracts notes (private key) and custom fields (public key)
- Writes files to
~/.ssh/with correct permissions:- Private key:
600(owner read/write only) - Public key:
644(owner read/write, others read) - Config:
600(owner read/write only)
- Private key:
Adding New SSH Keys
1. Generate Key Pair
2. Store in Bitwarden
3. Create Chezmoi Templates
Private key:private_dot_ssh/private_work_key.tmpl
private_dot_ssh/private_work_key.pub.tmpl
4. Add to Chezmoi
5. Update SSH Config
Template Functions Reference
bitwarden
Retrieves item by type and name:
bitwardenFields
Retrieves custom fields:
Best Practices
- Use separate SSH keys for personal and work
- Store all private keys in Bitwarden, never in git
- Use
ed25519algorithm for modern, secure keys - Set
IdentitiesOnly yesin SSH config to prevent key leakage - Encrypt SSH config with age if it contains sensitive hostnames
- Regularly rotate keys (annually recommended)
Troubleshooting
Permission Denied (publickey)
Key Not Found in Bitwarden
Ensure:- Item name matches exactly (case-sensitive)
BW_SESSIONis exported:echo $BW_SESSION- Vault is synced:
bw sync
Wrong Permissions
Chezmoi should set permissions automatically viaprivate_ prefix, but if needed:
Template Not Processing
If files have literal{{ }} content: