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.

Steps to use CA-signed SSH certificates for authentication:

  1. Open a terminal on the host designated to store the user certificate authority key with administrative privileges.
    $ whoami
    root
  2. Generate a dedicated SSH user certificate authority key pair on the CA host.
    $ 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.

  3. Restrict ownership and permissions on the CA private key file.
    $ 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.

  4. Copy the CA public key from the CA host to each SSH server and store it as /etc/ssh/ssh_user_ca.pub.
    $ 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.

  5. Add a TrustedUserCAKeys directive in /etc/ssh/sshd_config on each server pointing at the CA public key.
    $ 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.

  6. Validate the sshd configuration on each server before restarting the service.
    $ sudo sshd -t

    No output from sshd -t indicates that the configuration syntax is valid.

  7. Restart the ssh service on each server to apply the CA trust configuration.
    $ sudo systemctl restart ssh
  8. Generate a personal SSH key pair on the user machine if no suitable key exists yet.
    $ 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.

  9. Transfer the user public key file to the CA host for signing using a secure channel.
    $ scp ~/.ssh/id_ed25519_ca.pub ca-admin@ca-host:/tmp/user-id_ed25519_ca.pub
  10. Sign the user public key on the CA host to create a time-limited user certificate.
    $ 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.

  11. Copy the generated certificate back to the user machine and place it next to the private key.
    $ scp ca-admin@ca-host:/tmp/user-id_ed25519_ca-cert.pub ~/.ssh/id_ed25519_ca-cert.pub
  12. Ensure that the private key and certificate on the user machine have appropriate permissions.
    $ chmod 600 ~/.ssh/id_ed25519_ca ~/.ssh/id_ed25519_ca-cert.pub
  13. Inspect the certificate on the user machine to verify its principals, validity interval, and signing CA.
    $ 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.

  14. Initiate an SSH connection from the user machine so that OpenSSH automatically presents the certificate with the corresponding private key.
    $ 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.

  15. Run an SSH connection in verbose mode to confirm that a CA-signed certificate is being offered and accepted.
    $ 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.

  16. Check the server log to verify that the login used a CA-signed certificate rather than a static public key.
    $ 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.