Kokil Thapa - Professional Web Developer in Nepal
Freelancer Web Developer in Nepal with 15+ Years of Experience

Kokil Thapa is an experienced full-stack web developer focused on building fast, secure, and scalable web applications. He helps businesses and individuals create SEO-friendly, user-focused digital platforms designed for long-term growth.

SSH Certificate Authorities for Scale

By Kokil Thapa | Last reviewed: September 2026

Manual SSH key management breaks down once you pass a dozen servers and a handful of developers. Every new hire means copying public keys into authorized_keys on every box. Every departure means hunting stale keys nobody remembers. SSH Certificate Authorities for Scale solve this by replacing long-lived keys with short-lived, CA-signed certificates and a single trust anchor per host fleet. If you already run Ubuntu SSH server setup on production boxes, the jump to certificate-based auth is smaller than most teams expect.

What Are SSH Certificate Authorities and Why Do They Matter at Scale?

An SSH Certificate Authority is not a web TLS CA. It is a dedicated signing key pair used only to issue OpenSSH-format certificates. Those certificates bind a public key to a principal name, optional permissions, and an expiry time. Hosts and clients verify signatures against a pinned CA public key configured in sshd_config or ssh_config.

At small scale, static keys feel fine. I've seen the pain on real client projects once fleets grow. A law-firm portal might start on one VPS. Six months later there are staging, production, backup, and CI runners. Each developer laptop holds three key types. Someone rotates a deploy key and forgets the old one on a cron host. That is operational debt, not a security feature.

Certificate-based SSH centralizes trust. You configure each server once with TrustedUserCAKeys. After that, access changes happen at the CA layer. Issue a cert when someone joins. Stop issuing when they leave. Existing certs expire on their own. The model mirrors what you already know from PKI and certificate management basics, but the wire format and tooling are OpenSSH-native.

SSH CA Trust Model at ScaleSSH CA KeyOffline signerUser CertShort TTLHost CertHost identityLinux Server FleetTrustedUserCAKeys + TrustedHostCAKeysNo per-user authorized_keys sprawl
SSH Certificate Authorities for Scale: one CA signs credentials; every server trusts the CA public key instead of individual user keys.

OpenSSH has supported certificates since version 5.4. Modern Ubuntu 22.04 and 24.04 images ship OpenSSH 8.x or 9.x, so the feature is already on your servers. You do not need third-party agents unless you want a full identity layer like Step CA for internal PKI.

How Do You Set Up an OpenSSH Certificate Authority for Production?

Start with a dedicated CA key pair that never lives on production servers. Store the private key offline or in a hardware-backed vault. The public key gets copied to every host and client that should trust your CA.

Generate the CA key pair

Use Ed25519 for new CAs. It is fast, small, and aligns with current SSH key type guidance.

# On a secure admin workstation — not a production box
ssh-keygen -t ed25519 -f ssh_user_ca -C "prod-user-ca-2026"
ssh-keygen -t ed25519 -f ssh_host_ca -C "prod-host-ca-2026"

# Restrict private keys immediately
chmod 0400 ssh_user_ca ssh_host_ca

Keep separate CAs for user certs and host certs. If one is compromised, blast radius stays bounded. This is the same separation principle you apply when splitting TLS issuance from code-signing keys.

Configure servers to trust the user CA

Copy the user CA public key to each server. Then point sshd at it.

# /etc/ssh/sshd_config.d/50-ca.conf
TrustedUserCAKeys /etc/ssh/ca/user_ca.pub
AuthorizedKeysFile none

# Optional: require principals mapping
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u

Setting AuthorizedKeysFile none disables static key files entirely. That is the right end state for scale, but migrate gradually. Run CA auth alongside existing keys until your pipeline is stable. Pair this with the checks in harden SSH on Linux servers — certificates are not a substitute for sensible PermitRootLogin and network controls.

Sign a user certificate

A user cert wraps an existing public key. The CA signature proves identity for a limited time.

# Developer generates a normal key locally
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_prod

# CA admin signs it — valid 8 hours, principal = unix username
ssh-keygen -s ssh_user_ca \
  -I "kokil-laptop-2026-09" \
  -n kokil \
  -V +8h \
  ~/.ssh/id_ed25519_prod.pub

# Output: id_ed25519_prod-cert.pub (used automatically by ssh)

The -V flag sets validity window. Short TTLs limit exposure if a laptop is stolen. Eight to twenty-four hours works for human access. CI jobs may use five to fifteen minutes. The -I field is a certificate ID useful in logs and revocation lists.

Sign host certificates

Host certs let clients trust server identity without StrictHostKeyChecking accept-new gymnastics. Sign each host key at provisioning time.

# On the target server
ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key -N ""

# On CA workstation
ssh-keygen -s ssh_host_ca \
  -I "web-prod-01.example.com" \
  -h \
  -n web-prod-01.example.com,10.0.1.15 \
  -V +52w \
  /path/to/ssh_host_ed25519_key.pub

Deploy the resulting -cert.pub beside the host key. Clients configure @cert-authority entries in known_hosts or use KnownHostsCommand to fetch trusted host certs dynamically.

How Does SSH CA Authentication Compare to Manual Key Management?

Teams delay CA adoption because static keys still work. The trade-off becomes obvious once you count operational steps per access change.

CriteriaManual authorized_keysSSH CA at scale
OnboardingAppend key to every serverIssue one cert; servers already trust CA
OffboardingRemove key from N hosts; easy to miss oneStop signing; existing certs expire
Key lifetimeYears unless rotatedHours or days by policy
Audit trailScattered files, little metadataCert ID, principals, validity in CA logs
Host verificationManual known_hosts updatesHost certs + CA trust line
Initial setup costLowModerate — CA ops + sshd rollout

Manual keys win for a single VPS and one developer. CA wins everywhere else. On Deployer-managed fleets I maintain — shared EC2 hosts running Laravel legal-tech portals — the per-server key copy step was the first thing we automated away.

Onboarding: Manual Keys vs SSH CAManual: Copy key to each serverServer 1 → Server 2 → Server NCA: Sign once, access allSingle cert → entire fleetOffboarding GapManual: stale keys persist for yearsCA: TTL expiry closes access automatically
Manual SSH key onboarding scales linearly with servers; SSH Certificate Authorities for Scale reduce each access change to a single signing event.

How Do You Automate Certificate Issuance for a Growing Team?

Manual ssh-keygen -s commands do not scale past five people. Production systems wrap the CA in an API tied to your identity provider. The flow is predictable.

  1. Engineer authenticates to SSO — Okta, Google Workspace, or Azure AD.
  2. Access portal verifies group membership and requests a cert from the CA service.
  3. CA signs the submitted public key with appropriate principals and TTL.
  4. Engineer downloads the cert and connects with normal ssh user@host.
  5. Cert expires; user repeats login tomorrow.

Small teams can script this with a bastion and sudo-gated signing. Larger teams adopt Step CA or cloud identity extensions. HashiCorp Vault's SSH secrets engine is another option if you already run Vault for application secrets.

Map SSO groups to SSH principals explicitly. A developer might get principal deploy on staging only. Production access might require a break-glass group with one-hour certs. Document these mappings the same way you document SSH key-only auth setup policies today.

CI and deploy pipelines

GitLab CI, GitHub Actions, and Deployer need machine access too. Issue pipeline certs with very short TTL and narrow principals. Store the signing request behind your CI secret store. Never embed CA private keys in repository variables.

On projects using GitLab CI plus Deployer 7, I issue a five-minute cert at the start of the deploy job. The job connects, runs dep deploy production, and the cert expires before the runner is recycled. That beats long-lived deploy keys sitting in authorized_keys for years.

Principals file for role separation

Use AuthorizedPrincipalsFile to decouple Unix usernames from access roles.

# /etc/ssh/auth_principals/deploy
deploy
ci-readonly

# Sign with: ssh-keygen -s ssh_user_ca -n deploy,id_ed25519_prod.pub

One Unix account can accept multiple principals. Different teams receive different principal sets without creating shared login accounts. Avoid shared accounts entirely where possible.

Automated Cert Issuance PipelineSSO LoginAccess APICA SignSSH FleetPolicy ControlsGroup → principal mappingTTL: 8h humans · 5m CI
SSH Certificate Authorities for Scale work best when SSO, signing policy, and server trust config are wired into one repeatable pipeline.

What Certificate Extensions and Policies Should You Enforce?

OpenSSH certificates carry critical options that static keys cannot express cleanly. Use them.

  • force-command — restrict a cert to a single command, useful for backup scripts or git deploy users.
  • source-address — bind cert use to office or VPN CIDR ranges.
  • permit-X11-forwarding — disable unless explicitly needed.
  • permit-agent-forwarding — default off; see SSH agent forwarding risks.

Example: sign a read-only monitoring key locked to one command and one source network.

ssh-keygen -s ssh_user_ca \
  -I "monitoring-readonly" \
  -n monitoring \
  -V +24h \
  -O force-command=/usr/local/bin/readonly-check.sh \
  -O source-address=10.10.0.0/16 \
  -O clear-permit-agent-forwarding \
  monitoring_id_ed25519.pub

These flags encode policy in the credential itself. Even if someone exfiltrates the private key, the cert cannot open an interactive shell from a home ISP. That is defense in depth beyond what fail2ban and port hardening alone provide.

Align TTL policy with your broader rotation practice described in automate certificate rotation. SSH user certs are cheap to reissue. Err toward shorter lifetimes.

How Do You Handle Revocation and Host Trust at Scale?

Short TTLs reduce revocation urgency but do not eliminate it. A terminated employee with a valid eight-hour cert still has eight hours of access. You need a kill switch.

Key Revocation Lists

OpenSSH supports KRL — a compact binary revocation list generated from compromised cert IDs or raw public keys.

# Revoke by certificate serial / key
ssh-keygen -k -f /etc/ssh/revoked.krl -s ssh_user_ca -I "kokil-laptop-2026-09"

# sshd_config
RevokedKeys /etc/ssh/revoked.krl

Distribute KRL updates via configuration management — Ansible, cloud-init, or your existing Linux system administration playbook. Propagation delay is your revocation window. Pair KRL with very short TTL for defense in depth.

Host certificate rotation

Host certs typically last longer — thirty to fifty-two weeks. Track expiry the same way you track TLS cert expiry. A host cert expiring silently triggers the dreaded host key changed warning for every engineer. Add monitoring alerts thirty days before expiry. The lifecycle patterns in certificate lifecycle management apply directly.

For client-side trust at scale, replace static known_hosts with a CA line:

# ~/.ssh/known_hosts or ssh_config snippet
@cert-authority *.prod.example.com ssh-ed25519 AAAA...user_ca_pub...

Only hosts presenting a valid cert signed by your host CA pass verification. This closes MITM gaps that plague teams using SSH tunneling across jump hosts.

Revocation Layers at ScaleShort TTLAuto expiryKRL PublishInstant blockStop SigningNo new certsFleet sshd reads RevokedKeysConfig management pushes KRL to all hosts
Layer TTL expiry, KRL distribution, and signing policy to revoke SSH certificates quickly across a large fleet.

What Are Common Mistakes When Rolling Out SSH CAs?

Most failures are operational, not cryptographic.

CA private key on a server. If the CA key lives on a box that SSH users can reach, you have rebuilt centralized keys with extra steps. Keep signing offline or in a dedicated secrets service.

Skipping host certificates. Teams adopt user certs but ignore host certs. Engineers still click through host key warnings. Sign host keys during provisioning and automate renewal.

Principal sprawl without documentation. Ad-hoc principal names become as messy as ad-hoc Unix groups. Maintain a table mapping SSO groups to principals and permitted servers.

No logging. Enable verbose auth logging during rollout. Ship sshd logs to your central store. Certificate IDs in logs tell you which laptop accessed which box.

Mixing CA and static keys forever. Transitional dual mode is fine for a month. Permanent dual mode doubles audit surface. Set a cutoff date to disable AuthorizedKeysFile.

Generate strong CA passphrases with a proper entropy source. A local password generator beats keyboard mashing for offline CA keys you type once into a hardware token.

How Does SSH CA Fit Into Broader Supply Chain and Access Patterns?

SSH certs complement — not replace — other trust mechanisms. Developers can still sign Git commits with SSH keys using a separate key from their access cert. The signing key never needs shell access to production.

For Nepal-based teams on budget infrastructure, CA auth reduces support tickets. Small agencies charge Rs 2,000–5,000 (~USD 15–37) per manual key rotation ticket. Automating access pays for itself quickly. The same ops discipline supports trek booking platforms and legal-tech portals where uptime matters during peak season.

If you lack staff to run Step CA, start minimal. One Ed25519 CA key, an Ansible task to push TrustedUserCAKeys, and a signed shell script on a bastion beats unmanaged keys on forty servers. Expand when pain returns.

Official reference: the OpenSSH certificate format is documented in the ssh-keygen manual and the broader sshd_config specification. Read both before you disable static keys in production.

Key Takeaways

  • Deploy separate user and host CAs; never store CA private keys on production servers.
  • Configure TrustedUserCAKeys fleet-wide and migrate off authorized_keys once signing is automated.
  • Keep user cert TTL under twenty-four hours; CI certs under fifteen minutes.
  • Enforce policy via certificate extensions — force-command, source-address, no agent forwarding.
  • Combine short TTL with KRL distribution for fast revocation when someone leaves.
  • Sign host certificates and use @cert-authority in client config to eliminate MITM host warnings.

People Also Ask

Do I need special software to run an SSH CA?

No. OpenSSH ships everything required. You generate a CA key with ssh-keygen, sign certificates with ssh-keygen -s, and configure servers with TrustedUserCAKeys. Tools like Step CA add API and SSO layers but are optional for smaller fleets.

Can SSH certificates replace VPN access?

Often partially. Short-lived certs with source-address restrictions provide strong server authentication without a full VPN client. Many teams use a bastion plus SSH certs instead of site-to-site VPN for admin access. Application-level network segmentation still matters.

What key type should the CA use?

Ed25519 is the default choice in 2026. It produces small certs and fast verification. RSA CA keys remain valid for legacy compatibility but add size without benefit for greenfield rollouts.

How is an SSH CA different from TLS certificate authorities?

Both use PKI concepts — a root of trust, signed credentials, expiry. SSH certs authenticate shell access and are consumed by OpenSSH directly. TLS certs authenticate HTTPS and follow X.509. Different formats, same operational mindset.

Build Access That Scales With Your Fleet

SSH Certificate Authorities for Scale turn access management from a file-editing chore into a policy-driven pipeline. Start with one CA, one Ansible role, and eight-hour user certs. Add host certs, automated signing, and KRL distribution as your server count grows. The upfront setup pays back the first time someone leaves and you do not grep authorized_keys at midnight.

Need help hardening SSH across Ubuntu fleets, Laravel deploy pipelines, or mixed staging and production environments? See support and maintenance services or contact us to plan a rollout that fits your team size and budget.

Frequently Asked Questions

An SSH Certificate Authority is a dedicated OpenSSH signing key pair that issues short-lived user and host certificates. Servers trust one CA public key via TrustedUserCAKeys instead of hundreds of authorized_keys entries, centralizing access changes at the CA layer.

No. OpenSSH ships everything required. You generate a CA key with ssh-keygen, sign certificates with ssh-keygen -s, and configure sshd_config. Step CA or HashiCorp Vault are optional for larger identity pipelines.

Manual keys work for one VPS and one developer. Once you pass a dozen servers and a handful of developers, per-server key copying, stale keys, and offboarding gaps become operational debt. That is when CA auth pays off.

Generate separate Ed25519 user and host CA key pairs on a secure admin workstation, never on production servers. Copy the user CA public key to each host and add TrustedUserCAKeys in sshd_config. Sign user public keys with ssh-keygen -s, setting principals with -n and TTL with -V. Migrate gradually before setting AuthorizedKeysFile none.

Manual onboarding appends a key to every server; CA onboarding issues one cert because servers already trust the CA. Offboarding with static keys means hunting keys on N hosts; with CAs you stop signing and existing certs expire. Initial setup cost is higher, but each access change drops to a single signing event instead of linear server updates.

Eight to twenty-four hours works for human access, limiting exposure if a laptop is stolen. CI and deploy jobs should use five to fifteen minutes. On GitLab CI plus Deployer 7 projects, a five-minute cert at job start expires before the runner is recycled. Err toward shorter lifetimes because reissuing user certs is cheap.

Manual ssh-keygen -s commands do not scale past five people. Wrap the CA in an API tied to your identity provider: engineer authenticates via SSO, the portal verifies group membership, the CA signs the submitted public key with appropriate principals and TTL, and the engineer downloads the cert. Map SSO groups to SSH principals explicitly, with staging and production separated by group policy.

OpenSSH certificates carry options static keys cannot express cleanly. Use force-command to restrict a cert to a single command, source-address to bind use to office or VPN CIDR ranges, and clear-permit-agent-forwarding by default. Disable permit-X11-forwarding unless explicitly needed. These flags encode policy in the credential itself, so an exfiltrated key cannot open an interactive shell from an unauthorized network.

Short TTLs reduce urgency but a terminated employee with a valid eight-hour cert still has eight hours of access. OpenSSH supports KRL, a compact binary revocation list generated with ssh-keygen -k from compromised cert IDs. Configure RevokedKeys in sshd_config and distribute KRL updates via Ansible, cloud-init, or your existing configuration management. Pair KRL with very short TTL for defense in depth.

Teams that adopt user certs but skip host certs still click through host key warnings. Host certs let clients trust server identity without StrictHostKeyChecking accept-new gymnastics. Sign each host key at provisioning with ssh-keygen -s and the -h flag, deploy the -cert.pub beside the host key, and configure @cert-authority entries in known_hosts. This closes MITM gaps across jump hosts.

Most failures are operational, not cryptographic. Storing the CA private key on a reachable server rebuilds centralized keys with extra steps. Skipping host certificates leaves MITM warnings. Principal sprawl without documentation mirrors messy Unix groups. Missing auth logging loses certificate ID audit trails. Running CA and static keys forever doubles audit surface; set a cutoff date to disable AuthorizedKeysFile after a transitional month.

The CA private key must never live on production servers. Store it offline or in a hardware-backed vault, and restrict permissions immediately with chmod 0400 after generation. Keep separate CAs for user certs and host certs so a compromise of one bounds blast radius. Generate strong passphrases with a proper entropy source rather than keyboard mashing for offline keys.

GitLab CI, GitHub Actions, and Deployer need machine access too. Issue pipeline certs with very short TTL and narrow principals. Store the signing request behind your CI secret store and never embed CA private keys in repository variables. On Deployer 7 projects, issue a five-minute cert at deploy job start; the job connects, runs dep deploy production, and the cert expires before the runner is recycled.

AuthorizedPrincipalsFile decouples Unix usernames from access roles. A file at /etc/ssh/auth_principals/%u lists which principals each Unix account accepts. One Unix account can accept multiple principals, so different teams receive different principal sets without shared login accounts. Sign certs with ssh-keygen -n deploy for a deploy principal mapped to a dedicated Unix user, enabling role separation across staging and production.

Manual key onboarding scales linearly with servers; each hire and departure touches every box. Small Nepal agencies often charge Rs 2,000–5,000 (~USD 15–37) per manual key rotation ticket. Automating access through a CA reduces each change to one signing event and existing certs expire on their own, paying for moderate initial setup cost quickly on growing fleets.

Share this article

0 Comments

Leave a comment

Your email is not published. Comments appear once they have been read. Sign in to have your details filled in.

Quick Contact Options
Choose how you want to connect me: