Illustrative OpenSSH lesson with an engineer using a laptop beside a certificate-authentication diagram.

WIUNIX ACADEMY

OpenSSH user certificates: short-lived access and revocation in a loopback lab

Build a separate loopback-only sshd, verify its host key, issue a constrained user certificate and prove revocation affects new connections.

Advanced55 min readUpdated
Make this guide yours

YOUR SYSTEM. YOUR STEPS.

Where are you working?

Choose your OS and version. The prerequisites, commands and troubleshooting follow your environment.

Ubuntu 26.10Reviewed against official documentation ·

USE YOUR OWN VALUES

Configure this tutorial

Set the example values for your environment; related explanations and copy panels update together. Never enter passwords, private keys or tokens. Values stay in this tab and are not sent to the server or share links. Check actual DNS, certificates and network policy before running commands.

Different IP addresses, domains or ports? Open the settings below, change the values and select “Apply to tutorial”, then copy the updated commands.

Set values for my environment4 editable values

THE OUTCOME

What will you have at the end?

Build a separate loopback-only sshd, verify its host key, issue a constrained user certificate and prove revocation affects new connections.

Supported operating systems and versions

Primary-documentation review; no production execution or universal installation test is claimed. Examples assume existing tools on Linux and must be adapted to authorized deployment context.

Before you begin

  • Authorized operator access, existing tools named in the panels, and a private place to retain diagnostic evidence.
  • Use a staging environment or an approved read-only production investigation; review disruptive changes separately.

Keep the CA experiment away from production login

This is a single-host disposable lab with an existing non-root account, not a production CA architecture. It does not edit the system SSH configuration, publish a new network port or change the account’s usual keys. Production signing needs separately protected CA custody, audited issuance, clock discipline and a reachable revocation distribution path. Certificates authenticate a public key; they do not remove the need to verify the server host key.

01

LET’S BUILD

Check the selected distribution and required tools first

Run on the authorized diagnostic host or disposable lab VM. Compare the installed OS and required packages below with the selected path. Obtain missing tools from the distribution’s enabled official repositories through your approved package-management process; this workflow does not reinstall an existing server or switch its repository.

Ubuntu 26.10 is the reviewed default, with 26.04 LTS and 24.04 LTS alternatives. Check the actual package build and local configuration rather than assuming identical versions.

The client package is openssh-client. The normal ssh (sometimes ssh.socket) service is inspected only; this lab does not start/restart/reload it. Use an existing valid authorized non-root account. The Red Hat-family path generates RSA3072 lab keys because Ed25519 is unavailable in FIPS mode; this is not a claim of FIPS certification.

If the packaged privilege-separation prerequisite is missing, complete the native package setup on the disposable VM before this lab. Do not work around a missing /run/sshd by weakening privilege separation or changing the administration daemon.

bash

Authorized terminal on the host identified in this section

cat /etc/os-release
dpkg-query -W openssh-server openssh-client iproute2
command -v ssh ssh-keygen ss
systemctl show ssh.service -p ActiveState -p FragmentPath
sudo test -x /usr/sbin/sshd
sudo test -d /run/sshd
How do I know it worked?

Required packages and tools are identified; resolve missing tools before continuing.

02

LET’S BUILD

Confirm the account, port and exclusive directory

Use a disposable VM with the OpenSSH server already installed and a known unlocked non-root lab account labuser. Keep your normal administration session open. A missing account, locked account or occupied port is a stop condition. The sample does not create/unlock accounts or alter PAM policy. Verify the chosen path is new and not a symlink, mount or application data directory.

bash

Authorized Linux terminal

date -u +'%Y-%m-%dT%H:%M:%SZ'
ssh -V
getent passwd 'labuser'
test "$(id -u 'labuser')" -ne 0 || exit 1
sudo ss -lntp 'sport = :22222'
sudo test ! -e '/var/lib/academy-ssh-cert-lab' || exit 1
sudo mkdir -m 0700 -- '/var/lib/academy-ssh-cert-lab'
How do I know it worked?

The existing non-root account is correct, the port is unoccupied and the new root-only lab directory exists.

03

LET’S BUILD

Create separate CA, user and host key roles

Run on the lab VM. CA and user-key commands prompt interactively for passphrases; enter them only in the terminal, never the public-value form or a command argument. The separate unattended host key has an empty passphrase because sshd needs it, but remains inside the root-only lab directory. Do not reuse production keys. File prompts must never overwrite an existing key.

bash

Authorized Linux terminal

sudo ssh-keygen -t ed25519 -f '/var/lib/academy-ssh-cert-lab/user-ca' -C academy-lab-ca
sudo ssh-keygen -t ed25519 -f '/var/lib/academy-ssh-cert-lab/client' -C academy-lab-user
sudo ssh-keygen -t ed25519 -N '' -f '/var/lib/academy-ssh-cert-lab/host' -C academy-lab-host
sudo ssh-keygen -lf '/var/lib/academy-ssh-cert-lab/user-ca.pub'
sudo ssh-keygen -lf '/var/lib/academy-ssh-cert-lab/host.pub'
How do I know it worked?

Three independent keypairs exist with private files confined to the lab. Record public fingerprints, not private material.

04

LET’S BUILD

Create the explicit principal-to-account mapping

The privileged daemon reads a root-owned principals file for the selected account. It must contain exactly the allowed principal, not a wildcard. Initially the separate RevokedKeys file is an empty readable text file; later it will be atomically replaced by a KRL. An unreadable RevokedKeys file can fail all public-key authentication, so readability is a security and availability requirement.

AuthorizedPrincipalsFile may be opened after switching to the target account. Give the root-owned parent traverse-only access0711 and public principals0644 under0755; keep every private key root-owned0600. This exposes only known public paths, not directory listing or private keys, and prevents a false login failure caused by the initial0700 lab root.

bash

Authorized Linux terminal

sudo chmod 0600 '/var/lib/academy-ssh-cert-lab/user-ca' '/var/lib/academy-ssh-cert-lab/client' '/var/lib/academy-ssh-cert-lab/host'
sudo chmod 0711 '/var/lib/academy-ssh-cert-lab'
sudo install -d -m 0755 '/var/lib/academy-ssh-cert-lab/principals'
printf '%s\n' 'academy-operator' | sudo tee '/var/lib/academy-ssh-cert-lab/principals/labuser' >/dev/null
sudo chmod 0644 '/var/lib/academy-ssh-cert-lab/principals/labuser'
sudo install -m 0644 /dev/null '/var/lib/academy-ssh-cert-lab/revoked'
sudoedit '/var/lib/academy-ssh-cert-lab/sshd_config'
How do I know it worked?

A root-owned explicit account mapping and readable empty revocation file exist; edit only the new lab config.

Bind the isolated daemon only to loopback

This complete lab config has no Include of the system sshd_config. Raw authorized keys, password and keyboard-interactive authentication are disabled for this listener. Existing PAM account restrictions still apply and may reject a locked account. The forced id command proves authentication without granting an interactive shell or forwarding. Do not deploy this file over the production SSH configuration.

text · /var/lib/academy-ssh-cert-lab/sshd_config

File contents — not a shell command

Port 22222
ListenAddress 127.0.0.1
HostKey /var/lib/academy-ssh-cert-lab/host
PidFile none
UsePAM yes
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
AuthenticationMethods publickey
AuthorizedKeysFile none
TrustedUserCAKeys /var/lib/academy-ssh-cert-lab/user-ca.pub
AuthorizedPrincipalsFile /var/lib/academy-ssh-cert-lab/principals/%u
RevokedKeys /var/lib/academy-ssh-cert-lab/revoked
AllowUsers labuser
PermitRootLogin no
DisableForwarding yes
X11Forwarding no
PermitTTY no
ForceCommand /usr/bin/id
LogLevel VERBOSE
Explore all tutorials ↗