Skip to content

/commands/ssh-protocol/create-ssh-user-certificate

ssh-keygen -s ca -I id -n user key.pub: create an SSH user certificate

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash)updated
tool
SSH protocol
versions
OpenSSH 5.4+ (certificates), OpenSSH 10.x
os
linux, macos, windows

ssh-keygen -s user_ca -I alice@example -n alice -V +52w alice.pub signs Alice's public key with a certificate authority key and writes alice-cert.pub. A server that lists the CA's public key in TrustedUserCAKeys then accepts that certificate for the principals named with -n (here the Unix user alice), until the validity period ends. No authorized_keys entry per user is needed.

Sign a key and inspect the certificate

bash
ssh-keygen -q -t ed25519 -N '' -C 'user CA' -f user_ca
ssh-keygen -q -t ed25519 -N '' -C alice@laptop -f alice
ssh-keygen -s user_ca -I alice@example -n alice,deploy -V 20260101000000Z:20270101000000Z -z 42 alice.pub 2>&1 \
  | sed 's/ valid from.*//'
TZ=UTC ssh-keygen -L -f alice-cert.pub | grep -v SHA256

Output

Signed user key alice-cert.pub: id "alice@example" serial 42 for alice,deploy
alice-cert.pub:
        Type: ssh-ed25519-cert-v01@openssh.com user certificate
        Key ID: "alice@example"
        Serial: 42
        Valid: from 2026-01-01T00:00:00 to 2027-01-01T00:00:00
        Principals:
                alice
                deploy
        Critical Options: (none)
        Extensions:
                permit-X11-forwarding
                permit-agent-forwarding
                permit-port-forwarding
                permit-pty
                permit-user-rc

-V with two absolute UTC times keeps the example reproducible; in practice relative values such as -V +8h or -V -5m:+52w are common. ssh-keygen -L prints the times in the local time zone, hence TZ=UTC.

Options

OptionMeaning
-s CA_KEYPrivate key of the certificate authority that signs.
-I KEY_IDFree-form identity, written to the server log when the certificate is used.
-n alice,deployPrincipals: user names (or host names with -h) the certificate is valid for.
-V +52wValidity interval: absolute YYYYMMDD[HHMM[SS]] times (Z suffix for UTC), relative -/+ times, or always and forever.
-z 42Serial number, used by revocation lists.
-hCreate a host certificate instead of a user certificate.
-O source-address=10.0.0.0/8Restrict where the certificate may be used from; other -O options remove forwarding rights.
-L -f FILE-cert.pubPrint the contents of a certificate.

By default a user certificate gets the extensions permit-X11-forwarding, permit-agent-forwarding, permit-port-forwarding, permit-pty and permit-user-rc, as the output shows. -O clear removes them all; -O permit-pty adds back only what you list.

Trust the CA on the server

bash
# on the server, as root
cp user_ca.pub /etc/ssh/user_ca.pub
echo 'TrustedUserCAKeys /etc/ssh/user_ca.pub' >> /etc/ssh/sshd_config
sshd -t && systemctl reload sshd    # the unit is called ssh on Debian and Ubuntu

Pitfalls

  • A login that fails with Permission denied (publickey) while the certificate is offered usually means the principal does not match the target user, or the certificate has expired; the server log (journalctl -u ssh or /var/log/auth.log) names the reason.
  • Clocks matter: a certificate valid from "now" can be rejected by a server whose clock is behind. Start the interval a few minutes in the past (-V -5m:+8h).
  • Host certificates (-h) are trusted by clients through a @cert-authority line in known_hosts, which removes the first-connection fingerprint prompt.

FAQ

Does the user need anything besides the -cert.pub file?

No. Keep id_ed25519-cert.pub next to id_ed25519 and ssh offers the certificate automatically. If the files live elsewhere, point to it with CertificateFile in ~/.ssh/config or -o CertificateFile=PATH.

How do I revoke a certificate before it expires?

Add its serial number or key ID to a key revocation list with ssh-keygen -k, and set RevokedKeys in sshd_config to that file. Short validity periods reduce the need for revocation.

What happens if I leave out -n?

The certificate is signed without a list of principals. sshd does not accept such certificates for logins through TrustedUserCAKeys, so the login fails. Always set -n for user certificates.

Sources