SSH Certificates: Scaling Key Management for Enterprise Teams
Move beyond static SSH keys. Learn how SSH certificates enable time-limited access, role-based permissions, and centralized revocation for large teams.
Traditional SSH key management works fine for individuals: generate a key pair, copy the public key to every server, and you're done. But at scale — dozens of servers, hundreds of developers, frequent onboarding and offboarding — this approach breaks down.
Enter SSH certificates: a standardized way to issue time-limited, role-based credentials signed by a trusted Certificate Authority (CA).
The Problem with Static Keys
Consider a typical startup scenario:
- 50 developers
- 200 production servers
- Developers join and leave monthly
- Servers are provisioned and decommissioned weekly
With static keys, every change requires:
- Onboarding: Copy the new developer's public key to all 200 servers
- Offboarding: Remove the departing developer's key from all 200 servers
- Rotation: Periodically regenerate all keys and redistribute them
This is error-prone, slow, and doesn't scale.
How SSH Certificates Work
SSH certificates solve these problems by introducing a Certificate Authority (CA):
Traditional Flow (Static Keys)
Developer → Public Key → Copied to Every Server
Certificate Flow
Developer → Public Key → CA Signs Certificate → Server Trusts CA → Access Granted
The server only needs to trust the CA's public key. When a developer presents a certificate, the server verifies it was signed by the CA and grants access accordingly.
Certificate Components
An SSH certificate contains:
- Public key — The user's or host's key
- Identity — Username or hostname
- Valid principals — Which usernames this cert allows
- Validity period — Start and end timestamps
- Extensions — Permissions (e.g., can forward ports, can use agent)
- Critical options — Restrictions (e.g., source IP, command whitelist)
- Signature — Signed by the CA
Setting Up an SSH CA
Step 1: Generate CA Keys
# Generate CA key pair
ssh-keygen -t ed25519 -f ca_key -C "SSH CA Key"
# This creates:
# ca_key (private key — keep secure!)
# ca_key.pub (public key — distribute to servers)
Step 2: Configure Servers to Trust the CA
On each server, add the CA's public key to sshd_config:
# /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_key.pub
Restart sshd:
sudo systemctl restart sshd
Now any certificate signed by this CA will be accepted.
Step 3: Issue User Certificates
# Sign a user's public key
ssh-keygen -s ca_key \
-I alice@company.com \
-n alice,deployer \
-V +1w \
-O clear \
-O permit-port-forwarding \
-O permit-agent-forwarding \
alice_id_ed25519.pub
# This creates: alice_id_ed25519-cert.pub
Flags explained:
-I: Identity (logged in auth logs)-n: Valid principals (usernames this cert allows)-V: Validity period (+1w= one week from now)-O clear: Remove default extensions-O permit-*: Explicitly allow features
Step 4: Connect with the Certificate
ssh -i ~/.ssh/alice_id_ed25519 alice@server.example.com
SSH automatically uses the -cert.pub file alongside the private key.
Time-Limited Access
One of the biggest advantages of certificates is automatic expiration.
Issue a certificate valid for 8 hours:
ssh-keygen -s ca_key \
-I bob@company.com \
-n bob \
-V +8h \
bob_id_ed25519.pub
After 8 hours, the certificate is invalid. No need to manually revoke anything — the server rejects expired certificates automatically.
This is perfect for:
- Contractors: Issue certs matching contract duration
- Incident response: Grant temporary emergency access
- Audits: Ensure all access has an expiration date
Role-Based Certificates
Different roles need different permissions. Create separate CA signing keys for each role:
Developer Certificate
ssh-keygen -s ca_key_dev \
-I "dev-${USER}" \
-n "${USER}" \
-V +1w \
-O clear \
-O permit-port-forwarding \
-O permit-agent-forwarding \
dev_key.pub
Deployer Certificate
ssh-keygen -s ca_key_deploy \
-I "deploy-${USER}" \
-n deployer \
-V +24h \
-O clear \
-O permit-port-forwarding \
-O force-command=/usr/local/bin/deploy.sh \
deploy_key.pub
The force-command option restricts the deployer to running only the deployment script.
Admin Certificate
ssh-keygen -s ca_key_admin \
-I "admin-${USER}" \
-n root,admin,"${USER}" \
-V +4h \
-O clear \
-O permit-port-forwarding \
-O permit-agent-forwarding \
-O permit-pty \
admin_key.pub
Admin certs have shorter validity and broader access.
Host Certificates
So far we've discussed user certificates (proving who you are). SSH also supports host certificates (proving the server is legitimate).
Why Host Certificates Matter
Without host certificates, SSH relies on the known_hosts file to verify server identity. This leads to:
- TOFU (Trust On First Use): Blindly accepting the first connection
- MITM risk: An attacker could intercept the initial connection
- Key rotation pain: Updating
known_hostswhen servers change
Host certificates solve this by having servers present certificates signed by a trusted CA.
Setting Up Host Certificates
# Sign a host's public key
ssh-keygen -s ca_key_host \
-I "prod-web-01.company.com" \
-h \
-n prod-web-01.company.com,10.0.1.100 \
-V +52w \
/etc/ssh/ssh_host_ed25519_key.pub
# This creates: /etc/ssh/ssh_host_ed25519_key-cert.pub
The -h flag indicates this is a host certificate.
Configure sshd to use it:
# /etc/ssh/sshd_config
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
Clients trust the host CA:
# ~/.ssh/config
GlobalKnownHostsFile /etc/ssh/known_hosts_ca
Now clients automatically verify server certificates without manual known_hosts management.
Certificate Revocation
Sometimes you need to revoke a certificate before it expires (e.g., employee termination, compromised key).
Method 1: KRL (Key Revocation List)
Generate a revocation list:
ssh-keygen -k -f revoked_keys.krl ca_key.pub user_cert_to_revoke.pub
Configure sshd to check the KRL:
# /etc/ssh/sshd_config
RevokedKeys /etc/ssh/revoked_keys.krl
Update the KRL whenever you revoke certificates.
Method 2: Short Validity Periods
The simplest revocation strategy: issue certificates with very short validity (e.g., 1 hour). If you need to revoke access, just don't renew the certificate.
This requires an automated certificate issuance system but eliminates the complexity of KRLs.
Automated Certificate Issuance
For large teams, manual certificate signing doesn't scale. Build an automated system:
Architecture
Developer → Auth System (SSO/MFA) → Certificate API → CA Signs → Returns Cert
Example Flow
- Developer authenticates via SSO (Okta, Google Workspace)
- Backend verifies identity and role
- Backend calls
ssh-keygen -sor uses a library likegolang.org/x/crypto/ssh - Returns signed certificate to developer's SSH agent
- Developer connects to servers using the cert
Tools
Several open-source tools automate this:
- Teleport: Full SSH certificate management platform
- HashiCorp Vault: SSH secrets engine with certificate signing
- Smallstep: Modern PKI with SSH certificate support
- Certstrap: Simple self-hosted SSH CA
FoxTerm Integration
FoxTerm Pro includes built-in SSH certificate support:
Import CA-Signed Certificates
If your organization issues SSH certificates, import them into FoxTerm:
- Go to Settings → SSH Keys
- Click "Import Certificate"
- Select your private key and certificate files
- FoxTerm automatically uses the certificate for authentication
Automatic Certificate Renewal
FoxTerm can integrate with your certificate API to automatically renew certificates before they expire. Configure:
- Certificate endpoint URL
- Authentication method (API key, OAuth token)
- Renewal interval (e.g., every 6 hours)
FoxTerm handles the rest — you always have a valid certificate.
Host Certificate Verification
FoxTerm verifies host certificates automatically. If a server presents an invalid or expired certificate, FoxTerm warns you before connecting.
Migration Strategy
Moving from static keys to certificates? Here's a phased approach:
Phase 1: Set Up CA (Week 1)
- Generate CA keys
- Configure servers to trust the CA
- Test with a single user
Phase 2: Dual Authentication (Weeks 2-4)
- Issue certificates to pilot users
- Keep static keys as fallback
- Monitor auth logs for issues
Phase 3: Full Migration (Weeks 5-8)
- Issue certificates to all users
- Remove static keys from servers
- Document certificate workflows
Phase 4: Automation (Weeks 9-12)
- Build automated certificate issuance
- Integrate with SSO
- Set up monitoring and alerting
Best Practices
Security
- Protect the CA private key: Store in HSM or offline cold storage
- Use short validity periods: 8 hours for users, 52 weeks for hosts
- Separate CAs per environment: Dev, staging, prod should have different CAs
- Audit certificate issuance: Log every certificate signed
Operations
- Automate everything: Manual signing doesn't scale
- Monitor expiration: Alert before certificates expire
- Test revocation: Regularly verify that revoked certs are rejected
- Document procedures: Onboarding, offboarding, emergency access
Development
- Use strong key types: Ed25519 or RSA 4096+
- Include meaningful identities: Use email addresses or employee IDs
- Limit principals: Only include necessary usernames
- Restrict extensions: Only permit what's needed
Conclusion
SSH certificates transform key management from a manual chore into an automated, secure, scalable system. They enable:
- Time-limited access: No more stale keys
- Role-based permissions: Different access for different roles
- Centralized revocation: Revoke access instantly
- Host verification: Prevent MITM attacks
- Audit trails: Know who accessed what and when
For teams larger than a handful of developers, SSH certificates are not optional — they're essential infrastructure.
FoxTerm Pro supports SSH certificates out of the box. Download at foxterm.app.