SSH Keys — Setup, Management, and Security Best Practices 2026
Advertisement
Introduction
Why This Matters
Passwords are the weakest link in server authentication — they can be brute-forced, phished, or leaked in data breaches. SSH keys use asymmetric cryptography: the private key never leaves your machine, while the public key is freely distributed to servers. Even if a server is compromised, an attacker cannot derive your private key from the public key stored there.
For DevOps workflows — running Ansible playbooks, deploying via CI/CD, accessing production servers — SSH keys are the foundation of secure, automated access.
Generating SSH Keys
Use Ed25519, the modern standard. It is faster, more secure, and produces shorter keys than RSA:
# Generate an Ed25519 key pair
ssh-keygen -t ed25519 -C "your-email@example.com" -f ~/.ssh/id_ed25519
# The -C flag adds a comment (usually email) to identify the key
# The -f flag specifies the output filename
# For systems that do not yet support Ed25519, use RSA 4096
ssh-keygen -t rsa -b 4096 -C "your-email@example.com" -f ~/.ssh/id_rsa_legacyThis creates two files:
~/.ssh/id_ed25519— your private key (never share this)~/.ssh/id_ed25519.pub— your public key (copy this to servers)
Always set a strong passphrase when prompted. The passphrase encrypts the private key on disk, so even if your laptop is stolen, the key cannot be used without the passphrase.
Setting Correct Permissions
SSH is strict about permissions. If they are too permissive, SSH refuses to use the key:
# Secure the .ssh directory
chmod 700 ~/.ssh
# Secure the private key (owner read/write only)
chmod 600 ~/.ssh/id_ed25519
# Public key can be world-readable
chmod 644 ~/.ssh/id_ed25519.pub
# Authorized keys file
chmod 600 ~/.ssh/authorized_keysConfiguring the SSH Config File
The ~/.ssh/config file lets you define connection profiles so ssh production works instead of typing ssh -i ~/.ssh/prod_key deployuser@10.0.1.5 -p 2222:
# ~/.ssh/config
Host production
HostName prod.example.com
User deployuser
IdentityFile ~/.ssh/prod_key
Port 22
ForwardAgent no
Host staging
HostName staging.example.com
User devuser
IdentityFile ~/.ssh/staging_key
Port 22
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519_github
AddKeysToAgent yes
# Secure defaults for all hosts
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
PasswordAuthentication no
AddKeysToAgent yesThe wildcard Host * block applies secure defaults to all connections — disabling password authentication and enabling keep-alives to prevent dropped connections.
Using SSH Agent to Cache Passphrases
Typing your passphrase on every SSH command is impractical. The SSH agent caches decrypted keys in memory for the session:
# Start the agent (usually automatic in modern systems)
eval "$(ssh-agent -s)"
# Add your key (prompts for passphrase once)
ssh-add ~/.ssh/id_ed25519
# List cached keys
ssh-add -l
# Remove all keys from agent
ssh-add -DOn macOS, keys added to the agent persist across reboots via the system keychain when AddKeysToAgent yes and UseKeychain yes are set in ~/.ssh/config.
Copying Public Keys to Servers
The ssh-copy-id command appends your public key to a server's ~/.ssh/authorized_keys file:
# Copy default public key to a server
ssh-copy-id user@server.example.com
# Copy a specific key
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server.example.com
# Manual alternative (when ssh-copy-id is unavailable)
cat ~/.ssh/id_ed25519.pub | ssh user@server.example.com \
"mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"Hardening SSH Server Configuration
On servers you control, lock down /etc/ssh/sshd_config to reduce the attack surface:
# /etc/ssh/sshd_config — hardened settings
Port 22
Protocol 2
# Disable root login
PermitRootLogin no
# Disable password authentication (keys only)
PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM yes
# Allow only specific users
AllowUsers deployuser devuser
# Restrict algorithms to modern, secure ones
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com
# Timeouts
LoginGraceTime 30
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2After editing, reload the SSH daemon: sudo systemctl reload sshd. Always keep an existing session open while testing to avoid locking yourself out.
Common Mistakes
- Using RSA 2048 keys — RSA 2048 is considered borderline by 2026 standards. Use Ed25519 or at minimum RSA 4096 for new keys.
- No passphrase on private keys — An unencrypted private key file is as dangerous as a plain-text password. Always set a passphrase and use
ssh-agent. - Reusing one key across all services — Use separate keys for GitHub, production servers, staging, and CI/CD systems. Compromise of one key does not affect others.
- Enabling
ForwardAgent yesto untrusted servers — Agent forwarding allows a compromised server to use your cached keys to connect to other systems. Enable it only for trusted jump hosts. - Never rotating keys — Rotate keys annually at minimum, or immediately after any team member with key access leaves the organization.
Best Practices
- Generate a separate Ed25519 key for each service or environment: GitHub, production, staging, CI/CD.
- Store key passphrases in a password manager (1Password, Bitwarden) — not in plain text or notes.
- Audit
~/.ssh/authorized_keyson servers regularly and remove stale or unknown keys. - Use
ssh-keygen -l -f ~/.ssh/id_ed25519.pubto print the key fingerprint for verification. - In CI/CD pipelines, generate ephemeral deploy keys per pipeline or use short-lived signed certificates rather than long-lived static keys.
Key Takeaways
- Ed25519 is the recommended SSH key type in 2026 — it is faster and more secure than RSA 2048 or RSA 4096.
- Private keys must have
600permissions and~/.sshmust have700permissions — SSH refuses keys with broader permissions. - SSH agent caches decrypted keys in memory so passphrases only need to be entered once per session.
~/.ssh/configprofiles allowssh productionshorthand instead of typing full connection parameters every time.- Disable
PasswordAuthenticationon all production servers — key-only authentication eliminates brute-force attacks entirely. - Agent forwarding (
ForwardAgent yes) should only be enabled for trusted jump/bastion hosts, never for arbitrary servers. - Use separate key pairs per service so a compromised key does not give access to all systems.
- Rotate SSH keys at least annually and immediately when a team member with access departs.
Advertisement