SSH Key Rotation: Automating Credential Lifecycle
Implement automated SSH key rotation to reduce risk from compromised keys. Learn rotation strategies, automation tools, and zero-downtime updates.
SSH keys don't expire like passwords, but they should be rotated regularly. Compromised keys can provide unauthorized access indefinitely. Automated key rotation ensures security without manual overhead.
Why Rotate SSH Keys?
Risks of not rotating:
- Compromised keys provide permanent access
- Former employees retain access
- Key sprawl (hundreds of unknown keys)
- Compliance violations (SOC2, PCI-DSS require rotation)
Benefits of rotation:
- Limit exposure window
- Revoke access automatically
- Audit trail of key usage
- Meet compliance requirements
Rotation Strategies
Strategy 1: Time-Based Rotation
Rotate keys every N days:
# Rotate every 90 days
ROTATION_INTERVAL=90
Pros: Predictable, easy to schedule
Cons: Doesn't respond to incidents
Strategy 2: Event-Based Rotation
Rotate on specific events:
- Employee departure
- Security incident
- Compliance audit
- Key compromise suspected
Pros: Responsive to threats
Cons: Requires monitoring
Strategy 3: Hybrid Approach
Combine time-based and event-based:
- Regular rotation (90 days)
- Immediate rotation on security events
- Gradual rollout for large fleets
Manual Rotation Process
Step 1: Generate New Key
# Generate new key
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_new -C "user@example.com-2026"
# Start SSH agent with new key
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519_new
Step 2: Deploy New Key
# Copy new key to servers
for server in server1 server2 server3; do
ssh-copy-id -i ~/.ssh/id_ed25519_new.pub user@$server
done
Step 3: Test New Key
# Test connection with new key
for server in server1 server2 server3; do
ssh -i ~/.ssh/id_ed25519_new user@$server 'echo "Success"'
done
Step 4: Remove Old Key
# Remove old key from servers
for server in server1 server2 server3; do
ssh user@$server "sed -i '/old-key-comment/d' ~/.ssh/authorized_keys"
done
Step 5: Update SSH Config
# ~/.ssh/config
Host server1 server2 server3
IdentityFile ~/.ssh/id_ed25519_new
IdentitiesOnly yes
Automated Rotation Script
Basic Rotation Script
#!/bin/bash
# rotate-keys.sh - Automated SSH key rotation
set -e
SERVERS="server1 server2 server3"
OLD_KEY=~/.ssh/id_ed25519_old
NEW_KEY=~/.ssh/id_ed25519_new
BACKUP_KEY=~/.ssh/id_ed25519_backup
echo "Starting SSH key rotation..."
# Step 1: Backup current key
echo "Backing up current key..."
cp ~/.ssh/id_ed25519 $OLD_KEY 2>/dev/null || true
cp ~/.ssh/id_ed25519.pub $OLD_KEY.pub 2>/dev/null || true
# Step 2: Generate new key
echo "Generating new key..."
ssh-keygen -t ed25519 -f $NEW_KEY -N "" -C "rotated-$(date +%Y%m%d)"
# Step 3: Deploy new key
echo "Deploying new key to servers..."
for server in $SERVERS; do
echo " Deploying to $server..."
ssh-copy-id -i $NEW_KEY.pub user@$server
done
# Step 4: Test new key
echo "Testing new key..."
for server in $SERVERS; do
if ssh -i $NEW_KEY -o ConnectTimeout=5 user@$server 'exit' 2>/dev/null; then
echo " ✓ $server"
else
echo " ✗ $server - FAILED"
exit 1
fi
done
# Step 5: Remove old key
echo "Removing old key from servers..."
for server in $SERVERS; do
ssh user@$server "
# Remove old key (by comment)
sed -i '/rotated-/d' ~/.ssh/authorized_keys
# Keep only new key
cat >> ~/.ssh/authorized_keys <<EOF
$(cat $NEW_KEY.pub)
EOF
"
done
# Step 6: Update local config
echo "Updating SSH config..."
mv $NEW_KEY ~/.ssh/id_ed25519
mv $NEW_KEY.pub ~/.ssh/id_ed25519.pub
# Step 7: Restart SSH agent
echo "Restarting SSH agent..."
eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519
echo "✓ Key rotation complete"
Advanced Rotation with Ansible
# rotate-ssh-keys.yml
---
- name: Rotate SSH keys
hosts: all
become: yes
vars:
new_key_pub: "{{ lookup('file', '~/.ssh/id_ed25519_new.pub') }}"
tasks:
- name: Backup authorized_keys
copy:
src: /root/.ssh/authorized_keys
dest: /root/.ssh/authorized_keys.backup
remote_src: yes
- name: Add new key
authorized_key:
user: root
key: "{{ new_key_pub }}"
state: present
- name: Test new key
command: ssh -i /root/.ssh/id_ed25519_new localhost exit
delegate_to: localhost
ignore_errors: yes
register: test_result
- name: Remove old keys
authorized_key:
user: root
key: "{{ item }}"
state: absent
loop: "{{ old_keys }}"
when: test_result.rc == 0
Run:
ansible-playbook -i inventory rotate-ssh-keys.yml
Zero-Downtime Rotation
Overlap Period
Keep both old and new keys active during transition:
# Server authorized_keys
# Old key (valid until 2026-11-01)
ssh-ed25519 AAAA... old-key-comment
# New key (valid from 2026-10-17)
ssh-ed25519 AAAA... new-key-comment
Gradual Rollout
#!/bin/bash
# gradual-rotation.sh
# Phase 1: Deploy new key to 10% of servers
servers_10=$(shuf -n 10% servers.txt)
for server in $servers_10; do
ssh-copy-id -i new_key.pub user@$server
done
# Phase 2: Test and monitor
sleep 24h
# Phase 3: Deploy to remaining servers
servers_90=$(comm -23 servers.txt <(echo "$servers_10" | sort))
for server in $servers_90; do
ssh-copy-id -i new_key.pub user@$server
done
# Phase 4: Remove old keys
for server in $(cat servers.txt); do
ssh user@$server "sed -i '/old-key/d' ~/.ssh/authorized_keys"
done
Enterprise Key Management
SSH Certificate Authority
Use SSH certificates instead of keys:
# Generate CA key
ssh-keygen -f ca_key -N ""
# Sign user key
ssh-keygen -s ca_key -I user@example.com -n user -V +90d user_key.pub
# Server trusts CA
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub
Benefits:
- Automatic expiration
- Centralized trust
- No key distribution
- Easy revocation
HashiCorp Vault SSH Secrets
# Configure Vault
vault write ssh/config/ca generate_signing_key=true
# Issue short-lived certificate
vault write ssh/sign/otp_key_role \
ip=192.168.1.100 \
valid_principals=user
AWS Systems Manager
# Send SSH public key to instance
aws ssm send-ssh-public-key \
--instance-id i-1234567890abcdef0 \
--instance-os-user ec2-user \
--ssh-public-key file://key.pub
FoxTerm Key Rotation Support
FoxTerm simplifies enterprise key rotation:
Visual Key Management
- View all SSH keys across servers
- Track key age and usage
- Identify unused keys
- One-click rotation
Automated Rotation
- Schedule regular rotation (30/60/90 days)
- Zero-downtime overlap period
- Automatic testing and rollback
- Audit log of all rotations
Certificate Management
- SSH CA integration
- Automatic certificate renewal
- Expiration notifications
- Revocation management
Compliance Reporting
- Key inventory report
- Rotation compliance status
- Audit trail
- Export for compliance audits
Best Practices
- Rotate regularly — Every 90 days maximum
- Automate rotation — Scripts or tools like FoxTerm
- Test before removing — Verify new key works
- Overlap period — Keep both keys active during transition
- Use certificates — SSH CA for large fleets
- Audit regularly — Review authorized_keys files
- Monitor usage — Track which keys are used
- Backup before rotation — Keep old keys as backup
- Document process — Clear rotation procedures
- Compliance tracking — Meet SOC2/PCI-DSS requirements
Conclusion
SSH key rotation is essential for enterprise security. Automated rotation eliminates manual overhead while ensuring keys are regularly updated.
FoxTerm makes key rotation visual and automated, with scheduling, testing, and compliance reporting.
FoxTerm Pro includes enterprise SSH key rotation and management. Download at foxterm.app.