SSH keys are the standard way to access Linux servers. Password authentication is a liability — keys are harder to brute-force, cannot be guessed, and can be restricted in ways passwords cannot. Here is how to manage them properly.
Generate a strong SSH key pair
Use Ed25519 (modern, faster, more secure than RSA):
ssh-keygen -t ed25519 -C "aaron@workstation-2026" -f ~/.ssh/id_ed25519_crondaily
You will be prompted for a passphrase. Use one — it protects the key if the local machine is compromised.
If you need RSA for compatibility with older systems:
ssh-keygen -t rsa -b 4096 -C "aaron@workstation-2026" -f ~/.ssh/id_rsa_crondaily
Never use DSA or ECDSA. Ed25519 is the right choice for anything new.
Deploy a key to a server
ssh-copy-id -i ~/.ssh/id_ed25519_crondaily.pub user@server-ip
Or manually:
# On your local machine, copy the public key
cat ~/.ssh/id_ed25519_crondaily.pub
# On the server, append to authorized_keys
echo "ssh-ed25519 AAAA... aaron@workstation-2026" >> ~/.ssh/authorized_keys
The authorized_keys file lives in ~/.ssh/ for each user. For root, it is the same location.
Restrict key access by IP (Match and AllowUsers)
Once keys are deployed, restrict login to known IP addresses. Edit /etc/ssh/sshd_config on the server:
Match Address 203.0.113.0/24,198.51.100.42
AllowUsers aaron deploy-bot
Or per-user in ~/.ssh/authorized_keys:
from="203.0.113.0/24" ssh-ed25519 AAAA... aaron@workstation-2026
from="198.51.100.42" ssh-ed25519 AAAA... deploy-bot@ci-server
Restart SSH after config changes:
sudo systemctl restart sshd
Warning: always keep an active session open while testing SSH config changes. Locking yourself out of a remote server is a real risk.
Key management with ssh-agent
The ssh-agent holds decrypted private keys in memory so you do not type your passphrase repeatedly:
# Start the agent
eval "$(ssh-agent -s)"
# Add your key
ssh-add ~/.ssh/id_ed25519_crondaily
# List loaded keys
ssh-add -l
Add this to your shell profile for automatic startup:
# ~/.bashrc or ~/.zshrc
eval "$(ssh-agent -s)" > /dev/null
ssh-add -q ~/.ssh/id_ed25519_crondaily 2>/dev/null
Use a config file for multiple servers
Create ~/.ssh/config to avoid remembering hostnames, ports, and key paths:
Host crondaily-prod
HostName 203.0.113.42
User aaron
Port 22
IdentityFile ~/.ssh/id_ed25519_crondaily
ConnectTimeout 10
StrictHostKeyChecking accept-new
Host crondaily-staging
HostName 203.0.113.78
User aaron
IdentityFile ~/.ssh/id_ed25519_crondaily
Now connect with:
ssh crondaily-prod
Rotate SSH keys regularly
Key rotation is good practice, especially for server-to-server keys (deploy bots, CI systems).
Rotation process:
- Generate a new key pair on your workstation
- Add the new public key to the server’s
authorized_keysalongside the old key - Test login with the new key
- Remove the old public key from
authorized_keys - Store the old private key securely or destroy it
Do not delete the old key before verifying the new one works. This is the most common rotation mistake.
Server-level SSH security checklist
# In /etc/ssh/sshd_config:
# Disable password authentication
PasswordAuthentication no
# Disable root login
PermitRootLogin no
# Only allow specific users
AllowUsers aaron deploy-bot
# Change the default port (security through obscurity, but reduces noise)
Port 22022
# Disable empty passwords
PermitEmptyPasswords no
# Limit authentication attempts
MaxAuthTries 3
# Use a limited AllowUsers/AllowGroups rule
After any sshd_config change:
sudo sshd -t # Test config syntax first
sudo systemctl restart sshd
What to do if a key is compromised
- Remove the compromised public key from all servers immediately
- Generate a new key pair
- Deploy the new public key
- Audit server logs for any unauthorised access using the old key:
grep "ssh-ed25519" /var/log/auth.log - If there is evidence of compromise: treat the server as partially compromised and audit user accounts, cron jobs, and running processes
Agent forwarding: when to use it and when not to
SSH agent forwarding lets you use your local SSH keys from a remote server without copying the private key there. It is useful for deploying from a jump host.
Do not use agent forwarding on untrusted servers. A malicious server operator can use your forwarded agent connection to authenticate to other servers for as long as the agent is running.
Use dedicated deploy keys for automated access rather than agent forwarding.