Using CA-signed SSH certificates centralizes authentication and reduces the need to push individual public keys to every server. Certificate-based access enables short-lived credentials, clearer ownership, and easier revocation compared to managing long-lived keys in /home/user/.ssh/authorized_keys on each host.
In OpenSSH, a dedicated certificate authority key signs user public keys to create short-lived user certificates. Servers trust the CA by loading the CA public key via the TrustedUserCAKeys directive, and clients present a certificate that matches an allowed principal such as a username or role. The wire protocol remains the same as standard public key authentication, but the server validates the certificate’s signature, validity interval, and principals instead of a static key line.
CA-signed authentication introduces a single highly sensitive CA private key that must be tightly protected and backed up. Misconfigured CA trust or overly long validity intervals can weaken security or cause lockouts, so careful configuration, short lifetimes, and staged rollout are important on production systems. The steps below assume OpenSSH on Linux with systemd, using a user CA for authenticating human users.
Related: How to generate SSH key pairs
Related: How to connect with SSH using a private key
Related: How to configure passwordless SSH login
$ whoami
root
$ sudo ssh-keygen -t ed25519 -f /etc/ssh/ssh_user_ca -C "ssh user CA" -N "" Generating public/private ed25519 key pair. Your identification has been saved in /etc/ssh/ssh_user_ca Your public key has been saved in /etc/ssh/ssh_user_ca.pub The key fingerprint is: SHA256:eSYHwdOgaQIHj03wbf/uNwfD0wFmGUBPCMVuimZYr0I ssh user CA The key's randomart image is: +--[ED25519 256]--+ | +oo .+B+ooo | | O . oo.+o= | | . = * .o o.. | | +.. oo . | | o oSo+. . . | | E + o* = . | | . o . . + | | . . . o . | | . .o. o | +----[SHA256]-----+
ssh_user_ca acts as the root of trust for user logins, so loss or theft of this key allows forging certificates for any user.
$ chown root:root /etc/ssh/ssh_user_ca $ chmod 600 /etc/ssh/ssh_user_ca
Tight permissions help ensure only trusted administrators can sign new certificates.
$ scp /etc/ssh/ssh_user_ca.pub root@server1:/etc/ssh/ssh_user_ca.pub
scp is shown as an example; configuration management tools can distribute the CA public key at scale.
$ sudoedit /etc/ssh/sshd_config
/etc/ssh/sshd_config ##### snipped ##### TrustedUserCAKeys /etc/ssh/ssh_user_ca.pub ##### snipped #####
An incorrect TrustedUserCAKeys path prevents CA-signed users from logging in while leaving other authentication methods unchanged.
$ sudo sshd -t
No output from sshd -t indicates that the configuration syntax is valid.
Related: How to test SSH server configuration
$ sudo systemctl restart ssh
$ ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_ca -C "user@host.example.net" -N "" Generating public/private ed25519 key pair. Your identification has been saved in /home/user/.ssh/id_ed25519_ca Your public key has been saved in /home/user/.ssh/id_ed25519_ca.pub The key fingerprint is: SHA256:UlX5HagdbMCVdxR6CFzM5TFDw7hAX+kCjVcl+Jhysk4 user@host.example.net The key's randomart image is: +--[ED25519 256]--+ | ==@=X%*| | . *=%=**| | . BO=+o| | . o.+++..| | . S = . | | . E | | o | | . | | | +----[SHA256]-----+
Protecting the private key with a passphrase provides defense in depth if the client device is compromised.
$ scp ~/.ssh/id_ed25519_ca.pub ca-admin@ca-host:/tmp/user-id_ed25519_ca.pub
$ sudo ssh-keygen -s /etc/ssh/ssh_user_ca \ -I user@host.example.net \ -n user \ -V +52w \ /home/user/.ssh/id_ed25519_ca.pub Signed user key /home/user/.ssh/id_ed25519_ca-cert.pub: id "user@host.example.net" serial 0 for user valid from 2026-01-11T07:24:00 to 2027-01-10T07:25:36
The -V flag accepts intervals such as +1h, +1d, or +4w to limit certificate lifetime and reduce the impact of key compromise.
$ scp ca-admin@ca-host:/tmp/user-id_ed25519_ca-cert.pub ~/.ssh/id_ed25519_ca-cert.pub
$ chmod 600 ~/.ssh/id_ed25519_ca ~/.ssh/id_ed25519_ca-cert.pub
$ ssh-keygen -L -f ~/.ssh/id_ed25519_ca-cert.pub
/home/user/.ssh/id_ed25519_ca-cert.pub:
Type: ssh-ed25519-cert-v01@openssh.com user certificate
Public key: ED25519-CERT SHA256:UlX5HagdbMCVdxR6CFzM5TFDw7hAX+kCjVcl+Jhysk4
Signing CA: ED25519 SHA256:eSYHwdOgaQIHj03wbf/uNwfD0wFmGUBPCMVuimZYr0I (using ssh-ed25519)
Key ID: "user@host.example.net"
Serial: 0
Valid: from 2026-01-11T07:24:00 to 2027-01-10T07:25:36
Principals:
user
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
permit-user-rc
Principals usually correspond to allowed account names or roles, and the server compares them with the target login username.
$ ssh -i ~/.ssh/id_ed25519_ca -o CertificateFile=~/.ssh/id_ed25519_ca-cert.pub user@host.example.net hostname host
OpenSSH automatically loads a certificate named like id_ed25519_ca-cert.pub that lives next to the private key file in /homeuser.ssh.
$ ssh -vv -i ~/.ssh/id_ed25519_ca -o CertificateFile=~/.ssh/id_ed25519_ca-cert.pub user@host.example.net exit ##### snipped ##### debug1: Offering public key: /home/user/.ssh/id_ed25519_ca-cert.pub ED25519-CERT SHA256:UlX5HagdbMCVdxR6CFzM5TFDw7hAX+kCjVcl+Jhysk4 explicit debug1: Server accepts key: /home/user/.ssh/id_ed25519_ca-cert.pub ED25519-CERT SHA256:UlX5HagdbMCVdxR6CFzM5TFDw7hAX+kCjVcl+Jhysk4 explicit ##### snipped #####
Verbose logs help distinguish certificate-based logins from traditional key-based or password-based authentication.
$ sudo journalctl -u ssh --since "5 minutes ago" -o cat | grep "ED25519-CERT" | tail -n 1 Accepted publickey for user from 203.0.113.10 port 51390 ssh2: ED25519-CERT SHA256:UlX5HagdbMCVdxR6CFzM5TFDw7hAX+kCjVcl+Jhysk4 ID user@host.example.net (serial 0) CA ED25519 SHA256:eSYHwdOgaQIHj03wbf/uNwfD0wFmGUBPCMVuimZYr0I
Unexpected certificate IDs or principals in server logs can indicate misconfigured roles or unauthorized certificate issuance.