This site is an archive and is no longer updated.
    Back to Guides
    SSHIntermediate

    SSH Certificate Authority Setup

    Create your own CA with native OpenSSH (no extra software)

    12 min read
    LinkedInX
    SSH Certificate Authority Setup: Create your own CA with native OpenSSH
    TL;DR for SREs & Platform Engineers
    • • What it is: An SSH CA is just a key pair—no special software required
    • • Best practice: Separate CAs for users and hosts (security isolation)
    • • Key command: ssh-keygen -t ed25519 -f /etc/ssh/ca/user_ca

    Why use an SSH CA?

    Eliminate SSH key sprawl across your infrastructure, make offboarding instant (revoke the CA trust instead of hunting down authorized_keys), and enable bastionless access patterns. Replace hundreds of static keys with one trust anchor.

    1. What is an SSH Certificate Authority?

    Here's the surprising part: an SSH CA is just a key pair.

    No special software. No complex infrastructure. No certificate chain hierarchy. Just a key pair that you designate for signing. This is different from X.509 PKI where you typically need a full CA application or managed service—SSH certificates work with native OpenSSH out of the box.

    ┌─────────────────────────────────────────┐
    │       SSH Certificate Authority         │
    │                                         │
    │  ┌─────────────┐    ┌─────────────┐     │
    │  │ Private Key │    │ Public Key  │     │
    │  │   (signs)   │    │  (verifies) │     │
    │  └─────────────┘    └─────────────┘     │
    │        │                   │            │
    │        ▼                   ▼            │
    │   Keep SECRET         Distribute to    │
    │   (offline/HSM)      servers/clients   │
    └─────────────────────────────────────────┘
    The private key

    Signs certificates. Guard it carefully—this is the crown jewel.

    The public key

    Verifies signatures. Distribute it everywhere trust is needed.

    That's it. If you can generate an SSH key pair, you can create a CA.

    2. One CA or Two? The Architecture Decision

    Best practice: Separate CAs for users and hosts.

    ┌─────────────────┐         ┌─────────────────┐
    │    User CA      │         │    Host CA      │
    │                 │         │                 │
    │ Signs: user     │         │ Signs: server   │
    │ certificates    │         │ certificates    │
    │                 │         │                 │
    │ Trusted by:     │         │ Trusted by:     │
    │ SERVERS         │         │ CLIENTS         │
    └─────────────────┘         └─────────────────┘

    Why separate CAs? (Threat model perspective)

    Threat ScenarioSingle CA ImpactSeparate CAs Impact
    User CA compromisedAttacker can impersonate servers AND usersAttacker can only create fake user certs
    Host CA compromisedAttacker can impersonate servers AND usersAttacker can only create fake host certs
    Audit trail"Which type of cert was signed?"Clear separation in logs
    RotationMust rotate everything togetherRotate independently

    When single CA is acceptable:

    • • Small environments (< 20 servers)
    • • Lab/development setups
    • • You understand and accept the risk

    For production:

    Two CAs. Always.

    3. Creating the CA Key Pairs

    On your CA host, create a dedicated directory and generate two key pairs:

    Use a dedicated CA machine. Avoid running the CA on bastions, jump boxes, or developer laptops. The CA host should have minimal attack surface and restricted access.

    mkdir -p /etc/ssh/ca
    chmod 700 /etc/ssh/ca

    User CA (signs user certificates):

    ssh-keygen -t ed25519 -f /etc/ssh/ca/user_ca -C "user-ca@example.com"

    Host CA (signs host certificates):

    ssh-keygen -t ed25519 -f /etc/ssh/ca/host_ca -C "host-ca@example.com"

    Flags explained:

    FlagPurposeRecommendation
    -t ed25519Key typeEd25519 is modern, fast, secure
    -f <path>Output fileKeep CAs in dedicated directory
    -C <comment>Comment fieldLabel clearly for identification

    Output files:

    /etc/ssh/ca/
    ├── user_ca          # Private key - PROTECT THIS
    ├── user_ca.pub      # Public key - distribute to servers
    ├── host_ca          # Private key - PROTECT THIS
    └── host_ca.pub      # Public key - distribute to clients

    Set a strong passphrase when prompted. This protects the CA if the file is stolen.

    4. Protecting CA Private Keys

    The CA private key is the crown jewel. If compromised, attackers can forge any certificate.

    Protection levels (choose based on your risk tolerance):

    Level 1: Passphrase + file permissions (minimum)
    chmod 600 /etc/ssh/ca/user_ca
    chmod 600 /etc/ssh/ca/host_ca
    chown root:root /etc/ssh/ca/*

    Good for: Development, small teams, low-risk environments

    Level 2: Dedicated signing machine
    • • CA keys live on a single hardened server
    • • Network-isolated or tightly firewalled
    • • All signing requests go through this machine
    • • Audit logging on all signing operations

    Good for: Production environments, compliance requirements

    Level 3: Offline CA
    • • CA private key stored on air-gapped machine or USB
    • • Brought online only for signing
    • • Maximum security, minimum convenience

    Good for: High-security environments, root CAs

    Level 4: Hardware Security Module (HSM)
    • • CA key generated and stored in HSM
    • • Key never exists in extractable form
    • • Hardware-enforced access controls

    Good for: Enterprise, financial services, regulated industries

    Reality check: Most organizations land at Level 2. Level 1 is fine for getting started; move up as you scale.

    Decision guideline: If you're unsure, start at Level 2 and plan a path to Level 3 for your root CAs. Level 1 is acceptable only for development environments.

    5. CA Key Algorithm Choices

    Ed25519 is recommended, but here are your options:

    AlgorithmKey CommandProsCons
    Ed25519-t ed25519Fast, secure, small keysNot on very old systems
    ECDSA-t ecdsa -b 521Widely supportedLarger signatures
    RSA-t rsa -b 4096Universal compatibilityLarge keys, slower

    Check OpenSSH version:

    ssh -V
    # Ed25519 supported in OpenSSH 6.5+ (2014)

    Recommendation: Ed25519 unless you have ancient systems (RHEL 6, etc.) that don't support it. If you need maximum compatibility, create both Ed25519 and RSA CAs.

    FIPS/compliance note: If your organization requires FIPS 140-2 compliance and is RSA-only, mirror every Ed25519 CA with an RSA CA. Issue certs from both, letting clients negotiate what they support.

    6. Distributing CA Public Keys

    The public keys need to go to the right places:

    User CA public key → Servers

    Servers need to trust user certificates:

    # /etc/ssh/sshd_config
    TrustedUserCAKeys /etc/ssh/user_ca.pub
    Host CA public key → Clients

    Clients need to trust host certificates:

    # ~/.ssh/known_hosts
    @cert-authority *.example.com ssh-ed25519 AAAA...

    Distribution methods:

    MethodBest ForNotes
    Manual SCPSmall environmentsSimple but doesn't scale
    Configuration managementMedium/largeAnsible, Puppet, Chef
    Cloud-init / user-dataCloud VMsBake into instance launch
    Image bakingContainers, AMIsInclude in base image

    7. Signing Workflow

    Now your CA is ready to sign certificates.

    Sign a user certificate:

    ssh-keygen -s /etc/ssh/ca/user_ca \       # Sign with User CA
      -I "username@example.com-$(date +%Y%m%d)" \  # Key ID for audit logs
      -n username,admin \                     # Allowed principals (usernames)
      -V +24h \                               # Valid for 24 hours
      /path/to/user_key.pub                   # User's public key to sign

    Sign a host certificate:

    ssh-keygen -s /etc/ssh/ca/host_ca \       # Sign with Host CA
      -I "server01.example.com-$(date +%Y%m%d)" \  # Key ID for audit
      -h \                                    # Mark as HOST certificate
      -n server01.example.com,server01,10.0.1.50 \ # Hostnames/IPs this cert is valid for
      -V +52w \                               # Valid for 52 weeks (1 year)
      /etc/ssh/ssh_host_ed25519_key.pub       # Server's host public key

    The key difference: The -h flag marks it as a host certificate.

    → See SSH User Certificates for detailed user signing options.
    → See SSH Host Certificates for detailed host signing options.

    8. Validity Period Strategy

    How long should certificates be valid?

    User certificates: Short

    DurationUse Case
    1-8 hoursInteractive users, workday access
    24 hoursReasonable default
    1 weekInfrequent access, vacation coverage
    Never > 30 daysIf you need longer, reconsider your architecture

    Short validity = compromised cert is useless quickly = no revocation infrastructure needed.

    Incident response reality: If your mean time to detect a breach is measured in days, certificates longer than a week increase your blast radius. Match cert validity to your detection capability.

    For auditors: Short-lived user certs combined with central logging can often satisfy revocation requirements in practice—certificates expire before traditional revocation would take effect.

    Host certificates: Longer

    DurationUse Case
    1-4 weeksHigh-security, frequent rotation
    3-6 monthsReasonable default
    1 yearStable infrastructure, calendar-based renewal

    Why longer is acceptable for hosts: Host keys are already long-lived, hosts don't "log in"—they just exist, and renewal requires server access (operational overhead).

    9. Operational Procedures

    For user certificates with short validity, you need an efficient signing process:

    Option A: Manual signing (small scale)
    # User sends public key
    # Admin signs and returns certificate
    ssh-keygen -s /etc/ssh/ca/user_ca -I "user-$(date +%Y%m%d)" -n user -V +24h user.pub
    Option B: Self-service with approval (medium scale)
    • • User requests certificate through ticketing system
    • • Automated signing after approval
    • • Certificate returned via secure channel
    Option C: Automated signing service (large scale)
    • • HashiCorp Vault SSH secrets engine
    • • smallstep step-ca
    • • Venafi SSH Protect
    • • Custom signing service with API

    Recommended starting point: Option B for most teams. It balances security (approval workflow) with usability (self-service requests). Move to Option C when you hit 50+ users or need sub-hourly certificate validity.

    Certificate renewal check:

    # Check expiration
    ssh-keygen -L -f /etc/ssh/ssh_host_ed25519_key-cert.pub | grep "Valid:"
    
    # Example output:
    # Valid: from 2025-01-14T00:00:00 to 2025-07-14T00:00:00

    10. CA Key Rotation

    Eventually, you'll need to rotate CA keys. Plan for this:

    When to rotate:

    • • Suspected compromise
    • • Staff with CA access leaving
    • • Compliance requirements (annual rotation)
    • • Algorithm upgrades (RSA → Ed25519)

    Rotation procedure:

    1

    Generate new CA key pair

    ssh-keygen -t ed25519 -f /etc/ssh/ca/user_ca_2025 -C "user-ca-2025@example.com"
    2

    Distribute new CA public key alongside old

    Servers trust both old and new user CAs temporarily

    3

    Start signing with new CA

    All new certificates use new CA. Old certificates remain valid until expiration.

    4

    Remove old CA trust after transition period

    Once all old certificates have expired, remove old CA from TrustedUserCAKeys

    5

    Securely destroy old CA private key

    shred -u /etc/ssh/ca/user_ca_old

    Transition period: Typically 2x your longest certificate validity. If host certs are 6 months, plan 12-month transition.

    Note: User and Host CAs often have different rotation cadences. Document each separately in your runbooks—user CAs may rotate more frequently due to shorter cert lifetimes.

    11. Audit and Logging

    Track what gets signed:

    Basic logging:

    # Log every signing operation
    ssh-keygen -s /etc/ssh/ca/user_ca ... 2>&1 | tee -a /var/log/ssh-ca-signing.log

    Better: Structured signing script

    #!/bin/bash
    # sign-user-cert.sh
    # Minimal example – adapt paths and logging for your environment
    
    USER_KEY="$1"
    PRINCIPALS="$2"
    VALIDITY="${3:-+24h}"
    
    TIMESTAMP=$(date -Iseconds)
    KEY_ID="$(basename $USER_KEY .pub)-${TIMESTAMP}"
    
    # Sign the certificate
    ssh-keygen -s /etc/ssh/ca/user_ca \
      -I "$KEY_ID" \
      -n "$PRINCIPALS" \
      -V "$VALIDITY" \
      "$USER_KEY"
    
    # Log the operation
    echo "$TIMESTAMP | SIGN | $KEY_ID | principals=$PRINCIPALS | validity=$VALIDITY" >> /var/log/ssh-ca.log

    What to log:

    • • Timestamp
    • • Key ID
    • • Principals granted
    • • Validity period
    • • Who requested the certificate
    • • Who approved (if applicable)

    12. Quick Start Checklist

    Ready to set up your SSH CA? Here's the condensed version:

    Create CA directory
    mkdir -p /etc/ssh/ca
    chmod 700 /etc/ssh/ca
    Generate User CA
    ssh-keygen -t ed25519 -f /etc/ssh/ca/user_ca -C "user-ca@example.com"
    chmod 600 /etc/ssh/ca/user_ca
    Generate Host CA
    ssh-keygen -t ed25519 -f /etc/ssh/ca/host_ca -C "host-ca@example.com"
    chmod 600 /etc/ssh/ca/host_ca
    Distribute User CA public key to servers
    # On servers, /etc/ssh/sshd_config:
    TrustedUserCAKeys /etc/ssh/user_ca.pub
    Distribute Host CA public key to clients
    # On clients, ~/.ssh/known_hosts:
    @cert-authority *.example.com ssh-ed25519 AAAA...
    Test and document
    • • Test signing a user certificate (see SSH User Certificates for signing flags)
    • • Test signing a host certificate (see SSH Host Certificates for options)
    • • Document: Who can request? Who can sign? What validity periods?

    FAQ

    Can I use my regular SSH key as a CA?

    Technically yes, but don't. Use dedicated keys for CA purposes only. This keeps your CA keys separate from keys used for authentication.

    Do I need to set up my own CA, or should I use a service?

    Depends on scale:

    • • < 50 servers: DIY CA is fine
    • • 50-500 servers: Consider Vault or step-ca
    • • 500+ or compliance requirements: Enterprise solution (Venafi)

    What if I lose my CA private key?

    All certificates signed by that CA become unverifiable. You'll need to generate a new CA, redistribute the new public key everywhere, and re-sign all certificates. Backup your CA keys—store an encrypted backup in at least two locations with access limited to CA operators. Test your restore procedure annually.

    Can I have multiple User CAs?

    Yes. List multiple in TrustedUserCAKeys:

    TrustedUserCAKeys /etc/ssh/user_ca_1.pub /etc/ssh/user_ca_2.pub

    Use case: Different CAs for different teams or environments.

    How is this different from X.509 PKI?

    AspectSSH CertificatesX.509 PKI
    FormatOpenSSH proprietaryASN.1/DER standard
    Chain depthSingle levelMulti-level hierarchies
    RevocationNo built-in mechanismCRL, OCSP
    ComplexitySimpleComplex

    SSH certificates are simpler by design. That's a feature, not a bug.

    Related Guides

    SSH Certificate Series
    Related Concepts

    → Explore all SSH topics in our Guide Collection