SSH Key Management¶
Philosophy: One SSH key per device, never shared.
This document covers the complete SSH key architecture for accessing servers.
Table of Contents¶
- Why Device-Specific Keys
- Key Generation
- Adding Keys to Servers
- SSH Config Examples
- Key Rotation
- Emergency Access
- CRITICAL: Never Put SSH Keys in Secrets Managers
Why Device-Specific Keys¶
The Architecture¶
┌──────────────────────────────────────────────┐
│ CLIENT DEVICES │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ iPad │ │ MacBook │ │ PC │ │
│ │ │ │ │ │ │ │
│ │ Key A │ │ Key B │ │ Key C │ │
│ │ (private)│ │ (private)│ │ (private)│ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
└───────┼─────────────┼─────────────┼──────────┘
│ │ │
└─────────────┼─────────────┘
│ SSH
▼
┌──────────────────────────────────────────────┐
│ SERVERS │
│ ┌────────────────────────────────────────┐ │
│ │ ~/.ssh/authorized_keys │ │
│ │ │ │
│ │ ssh-ed25519 AAAA...iPad kavi@ipad │ │
│ │ ssh-ed25519 AAAA...MacBook kavi@mac │ │
│ │ ssh-ed25519 AAAA...PC kavi@pc │ │
│ └────────────────────────────────────────┘ │
└──────────────────────────────────────────────┘
Benefits of Device-Specific Keys¶
- Granular Access Control
- Know exactly which device accessed which server when
-
Audit trail in server logs:
kavi@macbookvskavi@ipad -
Easy Revocation
- Device lost or stolen? Remove only that key
- Other devices continue to work
-
No need to regenerate keys on all devices
-
Security Isolation
- Compromise of one device doesn't compromise others
- Each device has independent authentication
-
Follows principle of least privilege
-
Better Than Shared Keys
- ❌ Shared key anti-pattern: One key on USB drive, copied to all devices
- ❌ Problem: If one device is compromised, all access is compromised
- ❌ Problem: No way to track which device was used
- ✅ Device-specific: Each device has unique keypair
Key Generation¶
General Principle¶
Generate keys on the device where they will be used. Never generate a key on one device and copy it to another.
iPad¶
Prompts:
Enter passphrase (empty for no passphrase): [STRONG PASSPHRASE]
Enter same passphrase again: [REPEAT]
Generated files:
- ~/.ssh/id_ed25519_ipad (private key, NEVER share)
- ~/.ssh/id_ed25519_ipad.pub (public key, safe to share)
MacBook¶
Generated files:
- ~/.ssh/id_ed25519_macbook (private key)
- ~/.ssh/id_ed25519_macbook.pub (public key)
PC¶
Generated files:
- ~/.ssh/id_ed25519_pc (private key)
- ~/.ssh/id_ed25519_pc.pub (public key)
Passphrase Best Practices¶
Strong passphrase recommendations: - Minimum 15 characters - Mix of uppercase, lowercase, numbers, symbols - Use a password manager to generate and store - Store in device keychain (macOS Keychain, Windows Credential Manager)
Why passphrase is important: - Private key file can be stolen from device - Passphrase encrypts the private key - Without passphrase, stolen file = stolen access
Storing passphrases:
- macOS: Keychain Access (automatic with ssh-add --apple-use-keychain)
- Windows: SSH Agent with Windows Credential Manager
- Linux: ssh-agent + keychain manager
Adding Keys to Servers¶
Prerequisites¶
- You need initial access to the server (password, existing key, or server console)
- You have generated SSH keys on your device
- You have the public key content ready
View Your Public Key¶
# macOS/Linux
cat ~/.ssh/id_ed25519_macbook.pub
# Output example:
# ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFY4noi6kS88SH2OvEToerJZd4Ut/zQxfFE7yLFjcW1k kavi@macbook
Method 1: ssh-copy-id (Recommended)¶
# For Hetzner
ssh-copy-id -i ~/.ssh/id_ed25519_macbook.pub kavi@100.80.53.55
# For Kimsufi
ssh-copy-id -i ~/.ssh/id_ed25519_macbook.pub ubuntu@100.81.231.36
What this does:
- Copies your public key to ~/.ssh/authorized_keys on the server
- Sets correct permissions automatically
- Validates key format
Method 2: Manual Addition¶
If ssh-copy-id isn't available:
# 1. Copy public key to clipboard
cat ~/.ssh/id_ed25519_macbook.pub
# (copy the output)
# 2. SSH to server (with password or existing key)
ssh kavi@100.80.53.55
# 3. Add key to authorized_keys
echo "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFY4noi6kS88SH2OvEToerJZd4Ut/zQxfFE7yLFjcW1k kavi@macbook" >> ~/.ssh/authorized_keys
# 4. Set correct permissions
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh
# 5. Exit and test
exit
ssh kavi@100.80.53.55 # Should work without password
Adding Multiple Device Keys¶
Repeat the process for each device:
# From MacBook
ssh-copy-id -i ~/.ssh/id_ed25519_macbook.pub kavi@100.80.53.55
# From iPad
ssh-copy-id -i ~/.ssh/id_ed25519_ipad.pub kavi@100.80.53.55
# From PC
ssh-copy-id -i ~/.ssh/id_ed25519_pc.pub kavi@100.80.53.55
Result: All three devices can now SSH to the server.
authorized_keys will contain:
ssh-ed25519 AAAA...MacBook kavi@macbook
ssh-ed25519 AAAA...iPad kavi@ipad
ssh-ed25519 AAAA...PC kavi@pc
SSH Config Examples¶
Purpose of SSH Config¶
- Simplify SSH commands (
ssh hetznerinstead ofssh kavi@100.80.53.55) - Store connection settings (port, user, key file)
- Set keep-alive options
File Location¶
- macOS/Linux:
~/.ssh/config - Windows:
C:\Users\YourName\.ssh\config
Example Configuration¶
On MacBook (~/.ssh/config):
# Hetzner VPS (Germany)
Host hetzner
HostName 100.80.53.55
User kavi
IdentityFile ~/.ssh/id_ed25519_macbook
ServerAliveInterval 60
ServerAliveCountMax 3
# Kimsufi (Canada)
Host kimsufi
HostName 100.81.231.36
User ubuntu
IdentityFile ~/.ssh/id_ed25519_macbook
ServerAliveInterval 60
ServerAliveCountMax 3
# Storage Box (via SSH/SFTP)
Host storagebox
HostName u522581.your-storagebox.de
User u522581
Port 23
IdentityFile ~/.ssh/id_ed25519_macbook
# macOS Keychain integration
Host *
AddKeysToAgent yes
UseKeychain yes
On iPad (~/.ssh/config):
# Same as above, but change IdentityFile:
Host hetzner
HostName 100.80.53.55
User kavi
IdentityFile ~/.ssh/id_ed25519_ipad # Device-specific
ServerAliveInterval 60
ServerAliveCountMax 3
# ... repeat for other hosts
Configuration Options Explained¶
| Option | Purpose |
|---|---|
Host hetzner |
Alias for the connection |
HostName 100.80.53.55 |
Actual IP or domain |
User kavi |
Username on remote server |
IdentityFile ~/.ssh/id_ed25519_macbook |
Private key to use |
ServerAliveInterval 60 |
Send keepalive every 60 seconds |
ServerAliveCountMax 3 |
Disconnect after 3 failed keepalives |
AddKeysToAgent yes |
Add key to SSH agent |
UseKeychain yes |
(macOS) Store passphrase in Keychain |
Usage After Configuration¶
# Before: Long command
ssh kavi@100.80.53.55
# After: Short alias
ssh hetzner
# Works with scp, rsync, etc.
scp file.txt hetzner:/path/to/destination
rsync -avz /local/dir hetzner:/remote/dir
Key Rotation¶
When to Rotate Keys¶
- Annually: Proactive security practice
- Device lost/stolen: Immediately
- Device sold/given away: Before transfer
- Suspicious activity: If you suspect compromise
- Employee offboarding: When team member leaves
Rotation Process¶
Step 1: Generate new key on device
# Rename old key (backup)
mv ~/.ssh/id_ed25519_macbook ~/.ssh/id_ed25519_macbook.old
mv ~/.ssh/id_ed25519_macbook.pub ~/.ssh/id_ed25519_macbook.pub.old
# Generate new key
ssh-keygen -t ed25519 -C "kavi@macbook" -f ~/.ssh/id_ed25519_macbook
Step 2: Add new key to servers
ssh-copy-id -i ~/.ssh/id_ed25519_macbook.pub kavi@100.80.53.55
ssh-copy-id -i ~/.ssh/id_ed25519_macbook.pub ubuntu@100.81.231.36
Step 3: Remove old key from servers
# SSH to server
ssh hetzner
# Edit authorized_keys
nano ~/.ssh/authorized_keys
# Find and DELETE the old key line (look for old comment)
# Save and exit
# Repeat for all servers
Step 4: Test new key
Step 5: Delete old key locally
# After verifying new key works
rm ~/.ssh/id_ed25519_macbook.old
rm ~/.ssh/id_ed25519_macbook.pub.old
Revoking a Lost Device Key¶
If iPad is lost:
# 1. SSH from another device (MacBook)
ssh hetzner
# 2. Edit authorized_keys
nano ~/.ssh/authorized_keys
# 3. DELETE the line containing "kavi@ipad"
# Save and exit
# 4. Repeat for all servers
Result: iPad can no longer access servers, but MacBook and PC still can.
Emergency Access¶
What if ALL SSH keys are lost?¶
Hetzner VPS (Cloud-based):
1. Log in to Hetzner Cloud Console: https://console.hetzner.cloud
2. Select your server
3. Click "Console" (VNC access)
4. Log in with password (if set) or reset password
5. Add new SSH key to ~/.ssh/authorized_keys
Kimsufi (Dedicated Server):
1. Log in to OVH Manager: https://www.ovh.com/manager/
2. Select your Kimsufi server
3. Boot into rescue mode
4. Access via SSH (rescue mode credentials emailed)
5. Mount main filesystem
6. Add new SSH key to /mnt/home/ubuntu/.ssh/authorized_keys
7. Reboot to normal mode
Emergency SSH Key in Safe¶
Best practice: Keep ONE emergency SSH key pair: - Generate on a secure computer - Store private key on encrypted USB drive - Add public key to all servers - Put USB drive in physical safe - Only use in true emergency
Setup:
# Generate emergency key
ssh-keygen -t ed25519 -C "kavi@emergency" -f /path/to/usb/emergency_key
# Add to servers
ssh-copy-id -i /path/to/usb/emergency_key.pub kavi@100.80.53.55
ssh-copy-id -i /path/to/usb/emergency_key.pub ubuntu@100.81.231.36
# Store USB in safe
CRITICAL: Never Put SSH Keys in Secrets Managers¶
Why SSH Keys Must Stay Separate¶
❌ NEVER DO THIS:
1. Generate SSH key
2. Add to Infisical/Doppler
3. Fetch from secrets manager
4. Use to SSH
WHY THIS BREAKS:
- You need SSH to access the server
- Infisical runs ON the server
- Circular dependency: Need SSH to get SSH key
- If Infisical fails, you're locked out
The Correct Architecture¶
✅ CORRECT ARCHITECTURE:
SSH Keys: On client devices (iPad, MacBook, PC)
↓
SSH to Server: Using device-specific keys
↓
Access Infisical: Running on server
↓
Fetch Application Secrets: API keys, database passwords, etc.
What Goes Where¶
| Item | Location | Managed By |
|---|---|---|
| SSH Private Keys | Client device only | Device filesystem |
| SSH Public Keys | Server authorized_keys |
Manual or ssh-copy-id |
| API Keys | Infisical | Secrets manager |
| Database Passwords | Infisical | Secrets manager |
| Service Tokens | Infisical | Secrets manager |
| Infisical ENCRYPTION_KEY | Server ~/infisical/.env + encrypted backups |
Manual backup |
The Lockout Risk¶
Scenario: You put SSH keys in Doppler/Infisical
Day 1: Everything works fine
Day 30: Infisical server crashes
Result:
- Can't SSH to server (need Infisical to get SSH key)
- Can't access Infisical (it's on the server)
- Can't fix Infisical (can't SSH to server)
- TOTAL LOCKOUT
With device-specific keys:
Day 30: Infisical server crashes
Result:
- SSH to server with device key ✅
- Restart Infisical ✅
- Everything works again ✅
SSH Keys Are Authentication TO Infrastructure¶
Think of it this way: - SSH keys: The keys to the building - Secrets manager: A safe inside the building - Application secrets: Money in the safe
You can't store the building keys inside the safe in the building. You keep building keys on your person (device).
File Permissions¶
Correct Permissions¶
# Private key: Read/write for owner only
chmod 600 ~/.ssh/id_ed25519_macbook
# Public key: Read for all, write for owner
chmod 644 ~/.ssh/id_ed25519_macbook.pub
# SSH directory: Owner access only
chmod 700 ~/.ssh
# authorized_keys on server: Read/write for owner only
chmod 600 ~/.ssh/authorized_keys
Why Permissions Matter¶
SSH refuses to use keys with incorrect permissions:
❌ Permission 0644 for 'id_ed25519_macbook' are too open.
It is required that your private key files are NOT accessible by others.
This private key will be ignored.
Security reason: If other users can read your private key, it's compromised.
Troubleshooting¶
"Permission denied (publickey)"¶
Possible causes: 1. Public key not added to server 2. Wrong private key being used 3. Wrong username 4. SSH config pointing to wrong key
Debug steps:
# Verbose SSH output
ssh -v kavi@100.80.53.55
# Look for:
# "Offering public key: /Users/kavi/.ssh/id_ed25519_macbook"
# "Authentications that can continue: publickey" (means key rejected)
Fix:
"WARNING: UNPROTECTED PRIVATE KEY FILE!"¶
Cause: Private key has wrong permissions (too permissive)
Fix:
"Host key verification failed"¶
Cause: Server's fingerprint changed (reinstalled OS, different server, MITM attack)
Fix (if you know server was reinstalled):
SSH key not being used¶
Cause: SSH agent has too many keys (tries first 5, then gives up)
Fix:
# Clear SSH agent
ssh-add -D
# Add only needed key
ssh-add ~/.ssh/id_ed25519_macbook
# Or specify key explicitly
ssh -i ~/.ssh/id_ed25519_macbook kavi@100.80.53.55
Security Best Practices¶
- ✅ One key per device (not one key for all devices)
- ✅ Strong passphrases (15+ characters)
- ✅ Store in device keychain (macOS Keychain, Windows Credential Manager)
- ✅ Rotate annually (or when device changes hands)
- ✅ Revoke immediately (if device lost/stolen)
- ✅ Keep private keys private (never copy between devices)
- ✅ Use ed25519 algorithm (modern, secure, fast)
- ✅ Correct file permissions (600 for private, 644 for public)
- ❌ NEVER put in secrets managers (Infisical, Doppler, etc.)
- ❌ NEVER commit to git (even private repos)
- ❌ NEVER email keys (public keys OK, private keys NEVER)
- ❌ NEVER share keys between devices
Quick Reference¶
Generate Key¶
Add to Server¶
Test Connection¶
Remove Key from Server¶
View Public Key¶
Related Documentation¶
- First-Time Setup - Complete onboarding including SSH setup
- Emergency Access - What to do when locked out
- Infisical Secrets - What SHOULD go in secrets managers
- Tailscale VPN - SSH over VPN mesh network