Ending SSH Key Chaos: Setting Up Your Own SSH Certificate Authority
SSH keys often create conflicts and revision problems when managing server access; you can eliminate this chaos by setting up your own SSH Certificate Authority (CA).
Why Does SSH Chaos Occur?
Manually distributing SSH keys leads to inconsistencies and the problem of not removing old keys.
- Duplicate keys: When the same key is copied to multiple servers, access remains even if an employee's account is deleted.
- Revocation delay: It can take hours to collect all keys when an employee leaves, creating a security vulnerability.
These problems can be reduced by creating a central signing authority.
ℹ️ Why CA?
CA signs multiple host certificates with a single root private key; clients only need to trust the CA's public key, thus eliminating individual key management.
What is an SSH CA and How Does it Work?
An SSH CA is a certificate model supported by OpenSSH, similar to X.509 certificates but in its own format. Host or user certificates are generated using ssh-keygen -s.
- Root key: The CA's private key is stored in one place and has very limited access.
-
Signed certificates: The certificate given to the server carries the CA's signature and matches files like
HostCertificate. The certificate given to the user is trusted by the server via theTrustedUserCAKeysdirective and can have user-specific access restrictions via files likeAuthorizedPrincipalsFile.
This setup creates a trust chain: the client accepts the CA public key, verifies the host certificate signed by the CA, and grants access.
Workflow Summary Graph
Creating the CA Root Key
The root key should be created in a high-security directory and only accessible by root or via sudo privileges.
# Create a 4096-bit RSA key
sudo ssh-keygen -t rsa -b 4096 -f /etc/ssh/ca_key -N "" -C "My SSH CA"
# Save the public key to /etc/ssh/ca_key.pub
sudo chmod 600 /etc/ssh/ca_key
sudo chmod 644 /etc/ssh/ca_key.pub
WARNING: Using an empty password (-N "") for the CA private key poses a security risk. In production environments, it's strongly recommended to protect the CA private key with a password and store the key offline or in a Hardware Security Module (HSM).
The ssh-keygen output typically includes (output not shown):
- Private key:
/etc/ssh/ca_key - Public key:
/etc/ssh/ca_key.pub
A secure backup of the root key should be kept offline, such as on a USB drive or in an HSM.
Signing Host Certificates
Each server has a host key (e.g., ssh_host_rsa_key); this key needs to be certified with the CA's signature.
# Sign the host key on the server
# Replace ${HOSTNAME} and ${HOSTNAME}.example.com with your server names.
sudo ssh-keygen -s /etc/ssh/ca_key -I ${HOSTNAME} -h -n ${HOSTNAME},${HOSTNAME}.example.com /etc/ssh/ssh_host_rsa_key.pub
This command creates a certificate named ssh_host_rsa_key-cert.pub in the same directory. Add this certificate file to the HostCertificate line in the SSH daemon's sshd_config file:
# In /etc/ssh/sshd_config
HostKey /etc/ssh/ssh_host_rsa_key
HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub
WARNING: Incorrect configurations in sshd_config can disrupt SSH access. It's recommended to back up the file before making changes and, if possible, perform a dry run or validation step.
Restart the daemon after saving the changes:
sudo systemctl restart sshd
Client-Side: Making the CA Public Key Trusted
On client machines, the CA public key is added to ~/.ssh/known_hosts or /etc/ssh/ssh_known_hosts.
# Add the CA public key (global)
# Replace *.example.com with your domain.
sudo mkdir -p /etc/ssh
sudo tee -a /etc/ssh/ssh_known_hosts <<EOF
@cert-authority *.example.com $(cat /etc/ssh/ca_key.pub)
EOF
# For a personal user (optional, the above global configuration is sufficient)
# Replace *.example.com with your domain.
# This command adds the CA public key to the user's known_hosts file with the @cert-authority directive.
tee -a ~/.ssh/known_hosts <<EOF
@cert-authority *.example.com $(cat /etc/ssh/ca_key.pub)
EOF
This line accepts all host certificates under *.example.com signed by the CA.
User Certificate (Optional)
If you also want to manage individual user keys, you can create a user certificate with the same CA:
# Replace user01 and +52w with your username and validity period.
ssh-keygen -s /etc/ssh/ca_key -I user01 -n user01 -V +52w ~/.ssh/id_rsa.pub
This command produces a file named id_rsa-cert.pub. On the server, to make this user certificate trusted, you need to specify the CA's public key in the TrustedUserCAKeys directive in sshd_config.
Example sshd_config configuration:
# In /etc/ssh/sshd_config
TrustedUserCAKeys /etc/ssh/ca_user_keys.pub
Here, /etc/ssh/ca_user_keys.pub should contain the CA's public key that signed the user certificates.
Deployment and Management Strategies
When deploying SSH CA to multiple servers, the following practical tips are useful:
| Strategy | Description | Advantage | Disadvantage |
|---|---|---|---|
| Manual deployment | Copy files to each server using scp/rsync
|
Simple, low infrastructure need | High error potential, not scalable |
| Ansible Playbook | Use copy and lineinfile modules for automation |
Repeatable, version control | Requires Ansible setup |
| GitOps (Flux/ArgoCD) | Store CA files in a Git repo and deploy via CI/CD | Change tracking, easy rollback | Requires CI/CD pipeline |
Example Ansible task:
- name: Deploy SSH CA and host certificates
hosts: all
become: true
tasks:
- name: Copy CA public key
copy:
src: ca_key.pub
dest: /etc/ssh/ca_key.pub
mode: '0644'
- name: Ensure HostCertificate is configured
lineinfile:
path: /etc/ssh/sshd_config
regexp: '^HostCertificate'
line: "HostCertificate /etc/ssh/ssh_host_rsa_key-cert.pub"
- name: Restart sshd service
service:
name: sshd
state: restarted
This playbook deploys the CA public key and host certificate in one step.
Security and Maintenance
The CA's private key should never be transferred over the network; it should only be copied with physical access or stored in an HSM.
- Key rotation: Regularly rotating (e.g., every 6-12 months) the CA key and re-signing old certificates can enhance long-term security.
-
Revocation: OpenSSH uses Key Revocation Lists (KRLs) to revoke keys or certificates. KRLs are binary files created with
ssh-keygen -k. The list of revoked keys (revoked_keys) is specified insshd_configwith theRevokedKeysdirective.
WARNING: The ssh-keygen -R command removes a key from known_hosts, it does not create a revocation list. Use ssh-keygen -k for key revocation.
Conclusion
Setting up your own SSH Certificate Authority eliminates key conflicts, centralizes access management, and simplifies revocation processes.
- Step 1: Create the CA root private key in a secure location and protect it with a password.
-
Step 2: Sign server host keys with the CA and add the
HostCertificatedirective tosshd_config. -
Step 3: Make the CA public key a trusted source on client machines using the
@cert-authoritydirective. - Step 4: Scale deployment with automation (Ansible, GitOps).
This setup enhances both security and operational efficiency; planning for CA rotation and revocation strategies is recommended as a next step.
Top comments (0)