Eliminating ~/.ssh/authorized_keys Sprawl with a Private step-ca SSH Certificate Authority
Managing fleets of Linux hosts using static ~/.ssh/authorized_keys files creates severe operational debt and long-term security vulnerabilities. As engineers join, change projects, or leave an organization, perpetual public keys (ssh-rsa or ssh-ed25519) accumulate across dozens of servers without centralized inventory or automated revocation.
If an engineer’s laptop is compromised by malware or a private key is inadvertently leaked, an attacker secures indefinite, unmonitored shell access to production environments. In regulated sectors such as Fintech Startups (Neobanks) or high-throughput compute nodes in Astronomy & Space Observatories, static key distribution directly violates the access control mandates of ISO 27001, SOC 2, and NIS2.
The Zero-Trust solution is not managing static files with Ansible; it is eliminating authorized_keys entirely. By deploying an internal SSH Certificate Authority (CA) using step-ca integrated with your corporate identity provider (OIDC with MFA/Passkeys), developers no longer possess permanent keys. Instead, they authenticate each morning to receive short-lived OpenSSH certificates valid for only 12 hours.
At Webxtek Studio, where we engineer hardened perimeters for critical systems, this methodology expands upon the surface reduction framework established in our CISA, NSA & FBI Emergency Playbook: PHP, Node.js & Port Hardening.
Below I outline the cryptographic mechanics of native OpenSSH certificates and provide the end-to-end deployment runbook with step-ca on Debian/Ubuntu Linux.
1. From Brass Keys to Ephemeral Cards: Architecture of Native OpenSSH Certificates
To eliminate static authorized_keys sprawl across your Linux fleet, you must establish an internal SSH Certificate Authority with step-ca, configure TrustedUserCAKeys and AuthorizedPrincipalsFile in server sshd_config files, and authenticate engineers via OIDC to issue ssh-ed25519-cert-v01@openssh.com certificates valid for 12 hours.
Many systems administrators have used OpenSSH for over a decade without realizing that, since version 5.4, the protocol natively supports a lightweight SSH Certificate Authority (SSH CA) framework, documented in the official OpenBSD sshd_config manual.
Unlike heavy X.509 certificates used in HTTPS (which require complex ASN.1 parsing libraries), OpenSSH certificates (ssh-ed25519-cert-v01@openssh.com) are clean, deterministic binary structures tailored specifically for terminal access. An OpenSSH certificate packages the user’s ephemeral public key alongside immutable metadata cryptographically signed by your CA’s private key:
Zero-Trust SSH Authentication Workflow with step-ca and OIDC:
1. Shift Start (09:00):
The engineer executes 'step ssh login' in their laptop terminal.
2. Identity Verification:
step-ca redirects to the corporate Identity Provider (OIDC + FIDO2 Passkey).
3. In-Memory Issuance:
step-ca generates an ephemeral keypair and signs a User Certificate:
- Identity (Key ID): "josue@webxtek.com"
- Principals (Authorized roles): ["sre-prod", "web-deploy"]
- Temporal Validity: 09:00 to 21:00 today (12-hour TTL)
- Key injected directly into ssh-agent in RAM (zero private keys on disk).
4. Server Connection:
The engineer runs 'ssh root@srv-db-01.x078.internal'.
5. Offline Mathematical Verification:
- Target Linux server reads /etc/ssh/ssh_user_ca.pub (TrustedUserCAKeys).
- Verifies the CA mathematical signature, confirms clock validity, and verifies
the "sre-prod" principal exists in /etc/ssh/auth_principals/root.
- Access granted instantaneously with zero ~/.ssh/authorized_keys files on disk!
Notice the two monumental architectural advantages of this model, powered by the open-source Smallstep step-ca engine:
- Eliminating the Trust On First Use (TOFU) Dilemma: In legacy SSH, connecting to a new server triggers the warning “The authenticity of host … can’t be established”. In practice, engineers type
yeswithout verifying fingerprints, enabling Man-in-the-Middle (MITM) attacks. With a Host CA,step-casigns each server’s identity (HostCertificate). Client workstations need only a single@cert-authority *.x078.internalentry in theirknown_hostsfile to cryptographically verify legitimate infrastructure on the first attempt, instantly rejecting rogue hosts. - Role-Based Access Control (RBAC via Principals): The target Linux server does not need individual user accounts for every team member. A database host simply knows that any valid certificate presenting the
role-db-adminprincipal can log in aspostgresorroot, while a certificate bearingrole-frontend-devcan only access staging environments aswww-data. To further isolate developer accounts requiring SFTP access, we combine this architecture with the chroot jail patterns detailed in our guide on HestiaCP Jailkit SSH Sandboxing & SFTP Hardening.
2. Field Implementation: Dual CA, OIDC, and sshd_config Hardening
Below is the production configuration we deploy across Debian 12 and Ubuntu 24.04 LTS servers. We will initialize the Certificate Authority, lock down destination servers, and automate developer access.
Step 1: Initializing step-ca with SSH Certificate Support and OIDC Provisioner
On an isolated, dedicated identity node (or within a secure enclave backed by a YubiKey HSM2), initialize step-ca with the --ssh flag. This provisions two distinct root keys: a User CA (for signing human certificates) and a Host CA (for signing server identities):
# 1. Initialize PKI and SSH Certificate Authority (generates Ed25519 User and Host CAs)
step ca init \
--ssh \
--name="Webxtek Internal Zero-Trust PKI" \
--dns="ca.internal.webxtek.com" \
--address="127.0.0.1:9000" \
--provisioner="admin@webxtek.com"
# 2. Add corporate Single Sign-On provider (Google Workspace, Okta, Keycloak, or Entra ID) via OIDC
step ca provisioner add "corporate-sso" \
--type=OIDC \
--ssh \
--client-id="webxtek-ssh-ca-client-id" \
--client-secret="OIDC_SECRET_HERE" \
--configuration-endpoint="https://accounts.google.com/.well-known/openid-configuration" \
--domain="webxtek.com"
Once step-ca is operational, export the two root public keys (ssh_user_ca_key.pub and ssh_host_ca_key.pub) for distribution across your fleet:
# Export User CA public key (deployed to /etc/ssh/ssh_user_ca.pub on all Linux servers)
step ssh config --roots > /tmp/ssh_user_ca.pub
# Export Host CA public key (deployed to client workstation known_hosts files)
step ssh config --host --roots > /tmp/ssh_host_ca.pub
Step 2: Signing Server Host Certificates
On each Linux server in your fleet (e.g., srv-prod-01.internal.webxtek.com), sign the server’s public host key (/etc/ssh/ssh_host_ed25519_key.pub) so it can cryptographically prove its identity to connecting clients:
# On target server (srv-prod-01):
# 1. Copy User CA public key to /etc/ssh/ssh_user_ca.pub
sudo install -m 0644 -o root -g root /tmp/ssh_user_ca.pub /etc/ssh/ssh_user_ca.pub
# 2. Issue Host Certificate for server Ed25519 key (valid for 30 days, renewed weekly)
sudo step ssh certificate \
"srv-prod-01.internal.webxtek.com" \
/etc/ssh/ssh_host_ed25519_key.pub \
--host \
--sign \
--provisioner="admin@webxtek.com" \
--principal="srv-prod-01.internal.webxtek.com" \
--principal="10.20.30.15" \
--not-after=720h
This outputs /etc/ssh/ssh_host_ed25519_key-cert.pub directly adjacent to the server host key.
Step 3: Hardening /etc/ssh/sshd_config and Defining Principals Mapping (RBAC)
Configure OpenSSH on the production server to trust your User CA, map authorized Principals to local Linux accounts, and explicitly disable reading ~/.ssh/authorized_keys files, preventing rogue static backdoors from ever functioning:
# 1. Create immutable Principals directory mapped to local system users
sudo mkdir -p /etc/ssh/auth_principals
# 2. Define authorized roles for 'root' or 'sysadmin' accounts
cat << 'EOF' | sudo tee /etc/ssh/auth_principals/root
sre-core
josue@webxtek.com
EOF
# 3. Define authorized roles for application deployment user 'deployer'
cat << 'EOF' | sudo tee /etc/ssh/auth_principals/deployer
sre-core
fullstack-devs
ci-deploy-bot
EOF
sudo chmod 0644 /etc/ssh/auth_principals/*
Next, deploy the hardened configuration block to /etc/ssh/sshd_config.d/10-webxtek-zero-trust-ca.conf:
# ============================================================================
# /etc/ssh/sshd_config.d/10-webxtek-zero-trust-ca.conf
# Zero-Trust Ephemeral SSH Certificate Architecture (Webxtek Studio)
# ============================================================================
# 1. Present Host Certificate signed by internal Host CA
HostKey /etc/ssh/ssh_host_ed25519_key
HostCertificate /etc/ssh/ssh_host_ed25519_key-cert.pub
# 2. Trust User Certificates signed by internal User CA
TrustedUserCAKeys /etc/ssh/ssh_user_ca.pub
# 3. Map certificate Principals to local Linux users (%u)
AuthorizedPrincipalsFile /etc/ssh/auth_principals/%u
# 4. ERADICATE STATIC KEYS: Completely ignore ~/.ssh/authorized_keys on disk!
AuthorizedKeysFile none
# 5. Modern Cryptographic Cipher Suites and Password Disablement
PasswordAuthentication no
KbdInteractiveAuthentication no
ChallengeResponseAuthentication no
PubkeyAuthentication yes
AuthenticationMethods publickey
PermitRootLogin prohibit-password
# Restrict accepted algorithms exclusively to Ed25519 certificates and AEAD ciphers
PubkeyAcceptedAlgorithms ssh-ed25519-cert-v01@openssh.com,sk-ssh-ed25519-cert-v01@openssh.com
KexAlgorithms sntrup761x25519-sha512@openssh.com,curve25519-sha25519,curve25519-sha256
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
# 6. Detailed Forensic Telemetry (Logs Key ID and Serial to journald)
LogLevel VERBOSE
Validate syntax before reloading the SSH daemon:
# Test sshd syntax and reload daemon without terminating active connections
sudo sshd -t && sudo systemctl reload ssh
Notice the security posture of AuthorizedKeysFile none paired with PubkeyAcceptedAlgorithms ssh-ed25519-cert-v01@openssh.com: even if an adversary manages to write a public key to /root/.ssh/authorized_keys, the OpenSSH daemon completely ignores the file and rejects any key lacking a valid CA signature. To audit server files continuously against unauthorized tampering, pair this setup with file integrity monitoring from our playbook on Wazuh SIEM on Linux: FIM & Automated Active Response. If you manage multi-tenant servers where developers or external vendors require SFTP and restricted shell access, sandbox those accounts using our guide on HestiaCP Jailkit SSH Sandboxing & SFTP Hardening.
3. Developer Workflow and Forensic Session Auditability
Security implementations often fail when they introduce cumbersome friction for engineers. With ephemeral certificates via step-ca, developer workflow (a priority we emphasize both in backend engineering and our UX/UI Design engagements) becomes faster and simpler than juggling multiple static private keys.
Daily Developer Workflow
On the client workstation, configure trust in the Host CA once:
# 1. Configure workstation to trust all servers signed by Host CA
echo "@cert-authority *.internal.webxtek.com,10.20.*.* $(cat /tmp/ssh_host_ca.pub)" >> ~/.ssh/known_hosts
# 2. Authenticate each morning via OIDC + MFA to inject 12-hour certificate into RAM
step ssh login josue@webxtek.com --provisioner="corporate-sso"
# 3. Inspect active certificate in memory
ssh-add -L | step ssh inspect
The step ssh inspect command outputs full forensic telemetry for the active in-memory credential:
/dev/stdin:
Type: ssh-ed25519-cert-v01@openssh.com user certificate
Public key: ED25519-CERT SHA256:9f8a7b6c5d4e3f2a1b0c9d8e7f6a5b4c3d2e1f0a
Signing CA: ED25519 SHA256:4d3c2b1a0f9e8d7c6b5a4f3e2d1c0b9a8f7e6d5c
Key ID: "josue@webxtek.com"
Serial: 14892039481029384
Valid: from 2026-10-20T09:00:12 to 2026-10-20T21:00:12
Principals:
josue@webxtek.com
sre-core
fullstack-devs
Critical Options: (none)
Extensions:
permit-X11-forwarding
permit-agent-forwarding
permit-port-forwarding
permit-pty
Full Forensic Auditability in Server Logs (journalctl)
On traditional servers where multiple engineers access shared accounts using static keys, audit logs record generic Accepted publickey for root entries.
With OpenSSH certificates and LogLevel VERBOSE, every authentication records the exact corporate email (Key ID), certificate serial number, and CA fingerprint in /var/log/auth.log and journald:
# Audit which engineer accessed root or deployer accounts and with which certificate
sudo journalctl -u ssh --since "today" | grep "Accepted publickey"
# Real log output:
# Accepted publickey for root from 10.66.66.12 port 54312 ssh2: ED25519-CERT SHA256:9f8a... ID josue@webxtek.com (serial 14892039481029384) CA ED25519 SHA256:4d3c...
4. Technical Comparison: Static Keys vs. step-ca Zero-Trust Architecture
| Operational & Security Dimension | Static Keys (~/.ssh/authorized_keys) | Ephemeral OpenSSH Certificates (step-ca + OIDC) | Real Operational Impact |
|---|---|---|---|
| Credential Lifetime | Infinite (valid for years until manually deleted) | 8 to 12 hours (expires mathematically at end of shift) | Risk of orphaned or forgotten access credentials drops to 0% |
| Private Key Storage | ~/.ssh/id_ed25519 stored on workstation disk |
Retained exclusively in volatile RAM (ssh-agent) |
Disk-scraping infostealers find zero valid private keys |
| Team Onboarding & Offboarding | Running Ansible/Puppet across fleets to add/remove keys | Zero server touches (simply toggle corporate SSO account) | Instant revocation across entire infrastructure in seconds |
| Server Identity Verification | Vulnerable TOFU model (users blindly click yes) |
Automated cryptographic proof via @cert-authority |
100% immunity against SSH Man-in-the-Middle attacks |
| Audit & Compliance (ISO / SOC 2) | Difficult to prove who accessed shared accounts | Every login records nominal Key ID (email) and Serial | Unimpeachable forensic audit trails without heavy bastion software |
By rooting your infrastructure evolution in Technical Consulting and relying on our engineering team for Managed Hosting, you eliminate access management debt while hardening your perimeter against identity-based breaches.
5. Emergency Revocation (RevokedKeys / KRL) and Production Checklist
If an engineer’s laptop is stolen at 11:00 AM while their certificate remains valid until 21:00, OpenSSH supports ultra-compact binary Key Revocation Lists (KRL) via RevokedKeys /etc/ssh/revoked_keys:
# Instantly revoke a certificate by its unique Serial number in an emergency
sudo ssh-keygen -k -f /etc/ssh/revoked_keys -s /etc/ssh/ssh_user_ca.pub <(echo "serial: 14892039481029384")
Before declaring your migration to SSH certificates complete, verify these five operational criteria:
- Maintain Out-of-Band Emergency Consoles (IPMI / KVM): Prior to applying
AuthorizedKeysFile noneand reloadingsshd, keep an active root SSH session open in a secondary terminal and ensure working console access (Hetzner vKVM, AWS Session Manager, or Proxmox Console). - Synchronize Server Clocks with Chrony (NTP): Because certificates rely on strict time windows, any server clock drifting by 10 minutes will reject newly minted certificates. Verify with
timedatectl statusthatSystem clock synchronized: yesis active across all nodes. - Disable Unnecessary Agent Forwarding (
AllowAgentForwarding no): On destination servers, disableAllowAgentForwarding. If an engineer must transit a bastion host, mandate ProxyJump (-J), which tunnels TCP without exposing the localssh-agentsocket. - Automate HostCertificate Renewal: Provision a weekly systemd timer on each host (
step ssh renew /etc/ssh/ssh_host_ed25519_key-cert.pub /etc/ssh/ssh_host_ed25519_key) to ensure server identity certificates never lapse. - Purge Legacy ~/.ssh/authorized_keys Files: Once all team members authenticate via
step-ca, remove legacy authorized_keys files to maintain pristine forensic hygiene.
True security does not involve burdening engineers with cumbersome password layers; it means replacing error-prone manual tasks with invisible cryptographic guarantees. At Webxtek Studio, we engineer this mathematical rigor across every system we build. Through our Technical Consulting, hardened Managed Hosting, and disciplined UX/UI Design, we help your organization operate with institutional-grade security and maximum delivery velocity.
[+] [ INDEX_DIRECTORY ] 19 topics ▼
- Below I outline the cryptographic mechanics of native OpenSSH certificates and provide the end-to-end deployment runbook with step-ca on Debian/Ubuntu Linux.
- 1. From Brass Keys to Ephemeral Cards: Architecture of Native OpenSSH Certificates
- 2. Field Implementation: Dual CA, OIDC, and sshd_config Hardening
- Step 1: Initializing step-ca with SSH Certificate Support and OIDC Provisioner
- Step 2: Signing Server Host Certificates
- Step 3: Hardening /etc/ssh/sshd_config and Defining Principals Mapping (RBAC)
- 3. Developer Workflow and Forensic Session Auditability
- Daily Developer Workflow
- Full Forensic Auditability in Server Logs (journalctl)
- 4. Technical Comparison: Static Keys vs. step-ca Zero-Trust Architecture
- 5. Emergency Revocation (RevokedKeys / KRL) and Production Checklist
- Author
- Frequently Asked Questions
- Why does the traditional ~/.ssh/authorized_keys model fail in security audits and scaling infrastructures?
- How does native OpenSSH certificate authentication operate without syncing certificate revocation lists (CRLs) every minute?
- How do Host Certificates eliminate Man-in-the-Middle attacks and TOFU known_hosts prompts?
- What happens if the central step-ca server goes offline? Are administrators locked out of target servers?
- Related Nodes
- Path Sequence
Frequently Asked Questions
Why does the traditional ~/.ssh/authorized_keys model fail in security audits and scaling infrastructures?
Because a static ssh-ed25519 or RSA public key copied to a server has no embedded expiration date. If an engineer departs the company, loses a laptop, or suffers local malware theft, that key grants perpetual access to every machine where it was placed, requiring manual node-by-node key scrubbing.
How does native OpenSSH certificate authentication operate without syncing certificate revocation lists (CRLs) every minute?
The OpenSSH daemon trusts only a single root public key from your Certificate Authority (configured via TrustedUserCAKeys). When an engineer logs in each morning via Single Sign-On (OIDC + MFA), step-ca signs an ephemeral SSH certificate in RAM valid for only 8 to 12 hours. At the end of the shift, the certificate expires mathematically without manual intervention.
How do Host Certificates eliminate Man-in-the-Middle attacks and TOFU known_hosts prompts?
Under traditional Trust On First Use (TOFU), users connecting to a new server are asked whether they trust the fingerprint, training staff to blindly type yes. With a HostCertificate signed by your CA and a @cert-authority entry in client known_hosts files, client laptops cryptographically verify server legitimacy from the first millisecond.
What happens if the central step-ca server goes offline? Are administrators locked out of target servers?
No. Unlike PAM modules that require network connectivity for every command, OpenSSH certificate validation is 100% local and autonomous: any engineer who has already obtained their daily 12-hour certificate continues accessing Linux servers even if step-ca or the OIDC provider is temporarily unreachable.
[ RELATED_NODES ]
> START_PROJECT
Need a website that earns trust, ranks in search, and gives your business a stronger digital presence? Start the conversation here.