How to rotate SSH keys when someone leaves
When someone leaves, remove their own SSH keys and reissue any shared key they could read: a new pair next to the old one, switch clients, revoke the old key.
Part of the guide
SSHSSH key pair
- Where to issue a new one
- man.openbsd.org/ssh-keygen.1
- What a leaked key reaches
- Every account on every host whose authorized_keys lists the public key, with that account's rights, unless key options restrict it.
- Can be scoped
- Partly
Some key types can be limited, others carry full rights.
- Expires
- None for plain keys; expiry-time= or a certificate validity adds one
- Switching keys
- Overlap windowRevokes at once
What Crunu does here
Crunu doesn't reissue keys at providers. It shows which values to replace and keeps the new one.
Build the list for a departure with the offboarding checklistOn this page
Someone leaving means two separate SSH jobs. Their own key needs no reissue at all: the private half was theirs, so remove their public key from every authorized_keys file and every service that trusts it. A shared key whose private half they could read, such as a deploy key or a team's server key, needs a real reissue: generate a new pair, add the new public key next to the old one on every host, move each client to the new private key, and then delete the old public key. An authorized_keys file holds one key per line, so both keys work during the switch and nobody gets locked out (sshd manual).
Crunu doesn't log in to your servers or edit authorized_keys. It keeps shared private keys as files in an environment, shows who received which version, and writes the new key to the machines that need it.
Where a public key is trusted
sshd reads public keys from the files named by AuthorizedKeysFile, by default .ssh/authorized_keys and .ssh/authorized_keys2 in the user's home directory (sshd_config). Every line is one key with an optional options field in front. The options are your scope controls, and a reissue is a good time to add them:
from=limits the key to hosts or addresses, including CIDR ranges.command=forces one command whenever the key is used and ignores what the client asked for.restrictturns off port, agent and X11 forwarding, PTY allocation and~/.ssh/rc, and will include future restrictions too.expiry-time=sets a date after which the key is no longer accepted.
Servers aren't the only places. Code hosting stores deploy keys, cloud providers inject keys into new machines, and removing a person from a cloud team doesn't necessarily remove their keys from machines already running. The pages on GitHub deploy keys and DigitalOcean cover two common cases.
Reissue a shared key without downtime
- Generate a new pair with
ssh-keygen. Without arguments it creates an Ed25519 key; the comment set with-Chelps you find the key on servers later. - Add the private key as a file in the Crunu environment that held the old one, for example
payments-api / production, with a path outside~/.ssh/such asdeploy/deploy_ed25519, and save. The new version is recorded with its author and time. - Append the new public key to
authorized_keyson every host and account that trusted the old one. Leave the old line in place for now. - Move each client to the new private key: run
crunu pullon the CI runner or server that connects, then test a login with the new key. - Delete the old public key's line from every
authorized_keysfile. For extra certainty, list it in the server's revoked keys file as well.
ssh-keygen -t ed25519 -C "deploy payments-api 2026-10" -f ./deploy_ed25519
crunu pull --env payments-api/production
ssh -i ~/deploy/deploy_ed25519 deploy@api-prod-1 truecrunu pull writes files with mode 0600 and refuses paths inside ~/.ssh/ unless you pass --allow-path for that run, so either keep deploy keys outside ~/.ssh/, as in this example, or allow the path explicitly.
Make the removal stick
Deleting a line works until someone pastes it back. RevokedKeys in sshd_config names a file of keys that sshd always refuses, written either as plain public keys, one per line, or as a key revocation list made with ssh-keygen -k. Two warnings from the manual: if that file isn't readable, public key authentication is refused for every user, and because sshd may read it on each attempt, replace it atomically rather than editing it in place.
ssh-keygen -k -f /etc/ssh/revoked_keys.krl ./old_deploy_ed25519.pubRemoving a key affects the next authentication. A session that is already open was authenticated before the change, so end the departing person's open sessions separately.
Keys that expire on their own
Plain key pairs never expire, which is why old keys pile up. OpenSSH certificates are the alternative. A host trusts a certificate authority listed in TrustedUserCAKeys, and you sign each user's key with ssh-keygen -s, using -V to set a validity interval (ssh-keygen). Outside that interval the certificate isn't valid, so a departure ends at the next expiry even if nobody edits a single server. Without -V, a certificate is valid from the Unix epoch to the distant future, and a certificate without principals isn't accepted through TrustedUserCAKeys.
When to reissue SSH keys
- A departure. Remove their personal keys everywhere, reissue every shared key they could read, and end their sessions. In Crunu, removing the person produces a reissue checklist of the files they received, such as a deploy key, by path.
- A leak. Remove the old public key and add it to the revoked keys file first, then distribute the new pair.
- A schedule. Shared keys have no built-in end date, so reissue them on a calendar or move to certificates.
What to rotate when a developer leaves puts SSH in the context of the whole departure, and the offboarding checklist builds the list for your stack.
Frequently asked questions
Something else? Write to support@crunu.com
Do I need to reissue a departing person's own SSH key?
No. Their private key was always theirs, so there is nothing to replace. Remove their public key from every authorized_keys file and every service that trusts it. Reissue only shared keys whose private half they could read.
Can two SSH keys work for the same account at the same time?
Yes. Each line of an authorized_keys file holds one key, so you add the new public key next to the old one, move every client to the new private key, and then delete the old line.
Do SSH keys expire?
A plain key pair never expires. The expiry-time option in authorized_keys sets a time after which sshd stops accepting a key, and certificates signed with ssh-keygen can carry a validity interval. By default a certificate is valid forever.
Does Crunu remove keys from authorized_keys on my servers?
No. Crunu doesn't manage server logins. It stores shared private keys as environment files, shows who received them, and writes the new key to machines with crunu pull. Editing authorized_keys on each host is your step.
Sources
Every source this page relies on, with the date we last checked it.
- OpenBSD manual: sshd(8), AUTHORIZED_KEYS FILE FORMAT · checked October 30, 2026
- OpenBSD manual: sshd_config(5) · checked October 30, 2026
- OpenBSD manual: ssh-keygen(1) · checked October 30, 2026