Quit shipping SSH keys around and embrace Certificate Authorities
Technical Briefing | 11/11/2026
Look, we’ve all been there. You stand up a new box, drop your public key into ~/.ssh/authorized_keys, and you’re good. Repeat that for ten boxes, then a hundred. Then someone leaves, and you need to revoke access across that sprawl. Or a server gets re-provisioned, changes its host key, and suddenly everyone connecting sees that nasty “Host key verification failed” warning. We fix it by adding it to known_hosts, again. This isn’t just a maintenance chore; it’s a security blind spot. It’s not Zero Trust; it’s ‘trust on first use’ that often devolves into ‘trust everyone, always’.
The old way isn’t going to scale (or let you sleep soundly)
That authorized_keys file? It’s a ticking time bomb. One playbook run with the wrong template or a clumsy sed command and suddenly someone’s locked out or, worse, new keys got added by accident. And revoking a specific key across a fleet of servers is a nightmare – are you *really* sure it’s gone everywhere? This bit me more than once in prod. Then there’s known_hosts. Every new server generates that initial warning. Most people just blindly add it or, even worse, disable host key checks entirely, which just defeats the entire purpose of host key verification. It’s a system built for convenience at a small scale, not for security or manageability when you’ve got dozens or hundreds of hosts.
Enter the SSH Certificate Authority: A grown-up approach to trust
Here’s where an SSH Certificate Authority (CA) changes things fundamentally. Think of it like a mini PKI for your SSH connections. Instead of each client having a static public key directly trusted by each server’s authorized_keys, you have a central CA key. This CA key signs *temporary* certificates for your users, and even for your servers themselves. The servers are then configured to trust *only* the CA’s public key, not individual user keys. It’s a fundamental shift in the trust model: you’re no longer distributing individual user public keys; you’re distributing a single CA public key and signing identities with it.
ssh-keygen -s user_ca -I "alice@mycorp" -n alice,ops-team -V '+1h' ~/.ssh/id_rsa.pub
This is how you fix your user access nightmare
With a user CA in place, your sshd_config on all servers gets a simple AuthorizedPrincipalsFile directive pointing to the CA’s public key. Then, when a user wants to connect, their *client* key presents a certificate signed by your CA, not their raw public key. That certificate can contain principals (like ‘alice’ or ‘ops-team’) that sshd checks against the server’s local principals file. And you can set short expiration times on those certificates, say, an hour. This automatically solves key rotation, limits blast radius if a user key is compromised, and makes revocation dead simple: just stop signing new certs for that user, or just revoke the CA’s key if it’s truly catastrophic. Much better audit, too, since your CA logs every certificate it signs.
- No more manual authorized_keys management across your fleet. Seriously, none.
- Short-lived credentials are the default. Compromised keys expire on their own.
- Centralized revocation: disable the user’s signing access at the CA, not on 100 servers.
- Better audit trails. Your CA logs every certificate it signs.
- Fine-grained control: certificates can restrict source IPs, force commands, or specify validity periods.
And what about those pesky known_hosts warnings?
User certificates are great, but what about the servers themselves? That’s where a *host* CA comes in. Just like with users, your servers generate their own SSH host keys, but instead of broadcasting them or relying on ‘trust on first use’, your host CA signs them. On the client side, your ssh_config (or global ssh_config) then just needs a HostCertificateAuthority directive pointing to your host CA’s public key. Now, *any* server whose host key is signed by your trusted host CA will be automatically accepted by the client. No more “Host key verification failed” warnings, no more manually adding keys to known_hosts, and if a server gets re-provisioned and its host key changes, it just gets a new signed certificate. It’s cleaner, safer, and significantly reduces connection friction.
Setting up SSH CAs isn’t a five-minute job. You’ll need to secure your CA private keys, plan your signing workflow, and integrate it into your provisioning. But it’s an investment that pays off dramatically in operational overhead reduction and a massive security uplift. This isn’t just about ticking a Zero Trust box; it’s about building a remote access system that actually makes sense at scale, without making you want to tear your hair out every time someone new joins or leaves the team.
