C.W.K.
Stream
Lesson 09 of 14 · published

Key Rotation

~15 min · rotation, expiration, ca-issued

Level 0Pinger
0 XP0/101 lessons0/12 achievements
0/150 XP to next level150 XP to go0% complete

Rotate keys on a calendar, not on a panic

SSH keys, like passwords, age. Quarterly rotation is the right cadence for a personal fleet — frequent enough to limit blast radius from undiscovered compromise, infrequent enough to not be daily ops toil. The procedure is mechanical once you've done it once.

The fleet-wide rotation procedure

  1. Generate a new key on each device with a fresh comment.
  2. Deploy the new public key to every server's authorized_keys alongside the old one.
  3. Update each device's ~/.ssh/config to use the new key.
  4. Test exhaustively from each device.
  5. Remove the old public key from every server.
  6. Delete the old private key from each device.

Steps 2 and 5 are the parallelizable parts — that's where your fleet helpers (Track 7) earn their keep.

Code

Manual rotation steps·bash
# 1. Generate new key, fresh comment
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_2026q4 \
    -C "$(whoami)@$(hostname -s)-2026q4"

# 2. Push new public key to every server (alongside old one)
for host in $(cat ~/.fleet/all.txt); do
    ssh-copy-id -i ~/.ssh/id_ed25519_2026q4.pub "$host"
done

# 3. Update ~/.ssh/config to point at the new key
# Host *
#     IdentityFile ~/.ssh/id_ed25519_2026q4

# 4. Test exhaustively
for host in $(cat ~/.fleet/all.txt); do
    ssh -i ~/.ssh/id_ed25519_2026q4 \
        -o IdentitiesOnly=yes \
        -o ConnectTimeout=5 \
        "$host" 'echo OK' || echo "$host FAILED"
done

# 5. Remove old public key from every server
OLD_FP=$(ssh-keygen -lf ~/.ssh/id_ed25519_OLD.pub | awk '{print $2}')
for host in $(cat ~/.fleet/all.txt); do
    ssh "$host" "
        cp ~/.ssh/authorized_keys ~/.ssh/authorized_keys.bak.\$(date +%s)
        ssh-keygen -f ~/.ssh/authorized_keys -R '$OLD_FP' 2>/dev/null || \
            sed -i.bak '/$OLD_COMMENT/d' ~/.ssh/authorized_keys
    "
done

# 6. Finally, delete old private key locally
rm ~/.ssh/id_ed25519_OLD ~/.ssh/id_ed25519_OLD.pub

External links

Exercise

Plan (don't necessarily execute) a quarterly rotation. Write down: which devices have keys today, which servers each key is authorized on, where you'd run the rotation script. The act of mapping it once tells you whether rotation is feasible by hand or whether you should set up SSH certificates first. For 5+ devices and 9+ servers, certificates probably win.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.