Your authorized_keys File Is a Liability. Use SSH Certificates Instead.
By Saket Jain Published Linux/Unix
Your authorized_keys File Is a Liability. Use SSH Certificates Instead.
Technical Briefing | 10/11/2026
You’ve probably managed SSH access with `authorized_keys` files for years. We all have. You drop a public key in, and boom, access granted. It works, it’s simple for a few servers, a few users. But what happens when ‘a few’ turns into hundreds of servers and dozens of engineers, or even contractors and temporary staff? I’ve seen environments where revoking access meant a frantic Ansible run, a dozen manual checks, and praying you didn’t miss a box. That’s not scalable, and it sure isn’t secure.
The inherent risks of sprawling `authorized_keys` files
The `authorized_keys` approach is fundamentally decentralized. Every server has its own truth, its own list of valid keys. You need to push keys out, manage which keys go where, and crucially, pull them back when someone leaves or a key gets compromised. Think about it: once a key is on a server, it’s there until you explicitly remove it. That’s a long-lived credential with a wide blast radius if things go sideways. And how do you audit who has access to what, beyond just checking host logs after a breach? Most times, you don’t, not effectively.
Enter SSH Certificates: Centralized Trust, Ephemeral Access
This isn’t some new, bleeding-edge protocol; SSH Certificates have been around and are seriously robust. Instead of distributing individual public keys to every server, you set up an SSH Certificate Authority (CA). Users submit their *own* public keys to the CA, which then signs them, creating a short-lived certificate. This certificate is what the user presents to the server, not their raw public key. The beauty is, your servers only need to trust the CA’s public key. This flips the model: servers don’t need a huge `authorized_keys` file; they just need `TrustedUserCAKeys` pointing to your CA’s public key in their `sshd_config`.
# On your CA server, assuming ca_key is your CA's private key:
# User's public key (e.g., id_rsa.pub) is copied to a temp file, say user_key_to_sign.pub
# Sign the user's public key, valid for 4 hours, for user 'jdoe', serial 5678:
ssh-keygen -s /etc/ssh/ca_key -V '+4h' -n jdoe -z 5678 user_key_to_sign.pub
That `ssh-keygen` command does the heavy lifting. The `-V ‘+4h’` is the game changer here: it sets the certificate to expire in just four hours. Short-lived credentials are a cornerstone of Zero Trust. The `-n jdoe` specifies the ‘principals’ (users/groups) this certificate is valid for, and `-z 5678` is a serial number for tracking, handy for revocation. What you get back is `user_key_to_sign-cert.pub`, which is what the user then combines with their private key to connect. On the server side, `sshd` sees the certificate, verifies its signature against your `TrustedUserCAKeys`, checks the validity period, and ensures the principal matches the requested user. If all that aligns, access granted. No individual public key management needed on that host.
With certificates, you’re verifying identity at the CA level, making every connection explicitly validated. This isn’t just about ‘trust but verify’; it’s about ‘never trust, always verify’. You can tie CA signing to your identity provider, revoke certificates centrally at the CA (or just wait for them to expire, which is far more common), and even issue certificates programmatically for CI/CD pipelines or ephemeral access. This gets you away from static, always-on access and moves you towards dynamic, time-bound, identity-verified connections. Shifting to SSH certificates is a change in mindset and infrastructure, yes. It’ll take some initial setup to get your CA running, integrate with your identity systems, and deploy the CA public key to your servers. But once you’re there, the headache of `authorized_keys` sprawl, the sleepless nights worrying about forgotten keys, and the painful audits will become a distant memory. Your operations team, and your auditors, will thank you.
