The ssoossh client
The client is what ssh invokes on your behalf. It generates a keypair, hands
the public key to the server, waits for your approval in a browser, and loads
the signed certificate into your ssh-agent – or writes key files when no agent
is available. Private keys never leave the machine. This page is the command
reference: what each subcommand does and what it accepts.
Install
Section titled “Install”Release packages are on the releases page.
| Platform | Package | Where it lands |
|---|---|---|
| Debian / Ubuntu | ssoossh-client_*.deb |
/usr/bin/ssoossh, sample config at /etc/ssoossh/ssoossh.yaml, inert SSH drop-ins under /etc/ssh |
| RHEL / Fedora | ssoossh-client_*.rpm |
same |
| Windows (amd64) | ssoossh-client_*_windows_amd64.msi |
per machine into Program Files\ssoossh, added to the system PATH; installs silently with msiexec /i … /qn |
| Windows | ssoossh-client_*.zip |
extract ssoossh.exe onto PATH (the only Windows package for arm64) |
| macOS | ssoossh-client_*_darwin_<arch>.pkg |
/usr/local/bin/ssoossh, man pages under /usr/local/share/man, the annotated defaults at /usr/local/share/ssoossh/ssoossh.yaml |
| macOS | ssoossh-client_*.zip |
the same files, unpacked by hand – extract ssoossh onto PATH |
There is one macOS package per architecture, darwin_arm64 for Apple
silicon and darwin_amd64 for Intel; the installer refuses the wrong one
rather than leaving you with a binary that will not run. Both the binary and
the package are Developer ID signed and notarized, so neither prompts
Gatekeeper. Check a download before opening it:
spctl --assess --type install -v ssoossh-client_1.2.3_darwin_arm64.pkgThe package writes nothing under /etc. It installs the annotated defaults
to /usr/local/share/ssoossh/ssoossh.yaml as a file to copy from – the
client reads /etc/ssoossh/ssoossh.yaml and then ~/.config/ssoossh.yaml,
and needs neither, since the same
defaults are compiled in. To remove it:
sudo rm -rf /usr/local/bin/ssoossh /usr/local/share/ssoossh \ /usr/local/share/doc/ssoossh-client \ /usr/local/share/man/man1/ssoossh*.1 \ /usr/local/share/man/man5/ssoossh.yaml.5sudo pkgutil --forget org.mikenestor.ssoossh-clientGlobal flags
Section titled “Global flags”These are persistent flags: every subcommand accepts them.
| Flag | Default | What it does |
|---|---|---|
-c, --config <file> |
none | Path to the ssoossh config file. Merged after every search-path location. A file named here that is missing or unparseable is a startup error for every command, ssh config and host principals included, unlike an absent search-path file. A search-path file that is there but will not parse is skipped with a warning on stderr. |
--server <url> |
none | Server address including scheme, for example https://example.com. https is assumed if the scheme is omitted. Overrides server in the config file. |
-v, -vv, -vvv |
off | Trace what the command is doing, to stderr. -v steps, -vv requests and files, -vvv bodies. |
--debug |
off | Print the resolved configuration, its sources, and key storage to stderr. Hidden from --help but supported; implies -v. |
-h, --help |
Help for the command. |
-v and --debug both have environment equivalents for invocations whose
command line belongs to ssh or cron. See
Diagnostics.
Exit status
Section titled “Exit status”| Status | Meaning |
|---|---|
0 |
Success, including the cases a command documents as succeeding without doing anything (a certificate still valid, nothing to remove). |
1 |
The command ran and failed: the server was unreachable, the request was denied, a file could not be written. |
2 |
The command was invoked wrongly: an unknown command or flag, a bad flag value, missing or extra arguments. The message ends with the --help command to run. |
Match exec treats any non-zero status as “do not connect”, so the
distinction matters only to scripts.
The commands
Section titled “The commands”| Command | Talks to the server | What it does |
|---|---|---|
ssh login |
yes | Authenticate via OIDC and load a signed certificate |
ssh logout |
yes | Remove ssoossh-managed keys and certificates |
ssh config |
no | Print the ssh_config recipes |
ssh proxycommand |
yes | Ensure a certificate, then relay stdio to the target |
ssh inspect |
yes | Print what the held certificates grant |
ca |
yes | Print the server’s CA public key |
host principals |
no | Answer sshd’s AuthorizedPrincipalsCommand |
host mapping |
no | Manage the local principal mapping file |
host check |
only for the CA keys | Check that this host’s sshd will accept ssoossh certificates |
service enroll |
yes | Enroll a keypair for unattended issuance |
service retrieve |
yes | Redeem an enrollment code for a certificate |
version |
no | Print version, commit, and build info |
The four offline commands (ssh config, host principals, host mapping,
version) make no network call at all. They still load configuration, because
even a command that never talks to the server has to know where its own local
files live.
ssoossh ssh login
Section titled “ssoossh ssh login”Generates a fresh keypair, sends the public key to the server, prints the
approval URL (and opens it in a browser when
try_open_browser is
set), and waits over SSE for the signed certificate. This
is what an ssh_config Match exec line runs.
A certificate that is already loaded and still valid is reused rather than replaced, so one approval covers every connection until it expires.
| Flag | Default | What it does |
|---|---|---|
--force |
off | Request a new certificate even if a valid one is already loaded |
--key-type <type> |
ecdsa |
Key algorithm to generate: ed25519, ecdsa, or rsa |
--key-size <n> |
384 for ecdsa |
Bits for rsa, curve for ecdsa; ignored for ed25519 |
--no-pty |
off | Do not request the permit-pty extension |
--no-agent-forwarding |
off | Do not request permit-agent-forwarding |
--no-port-forwarding |
off | Do not request permit-port-forwarding |
--no-x11-forwarding |
off | Do not request permit-X11-forwarding |
--no-user-rc |
off | Do not request permit-user-rc |
--key-type and --key-size override
sshkey.type and
sshkey.size; the --no-*
flags override the matching
certificate_extensions
keys.
# what ssh runs for youssoossh ssh login
# replace the loaded certificate with a fresh onessoossh ssh login --force
# a session that needs no forwarding of any kindssoossh ssh login --no-agent-forwarding --no-port-forwarding --no-x11-forwardingBy default the client asks for the full interactive extension set:
permit-pty, permit-agent-forwarding, permit-port-forwarding,
permit-X11-forwarding, and permit-user-rc. Asking for the full set is
always safe – the server narrows the request against its own configuration
before signing, and the approval page shows what survived. Asking for nothing
is not useful: narrowing is an intersection, so an empty request yields a
certificate that cannot open an interactive session.
Before requesting anything, ssh login verifies that the resolved key storage
will actually accept and release a key, using a throwaway keypair. That check
exists so a storage failure surfaces before you approve a certificate rather
than after.
ssoossh ssh logout
Section titled “ssoossh ssh logout”Removes the certificates ssoossh put in your ssh-agent – those signed by the configured CA – and nothing else. Your own keys are left alone. When key files are used instead of an agent, the files ssoossh wrote are deleted.
No flags beyond the global ones.
ssoossh ssh logoutssoossh ssh config
Section titled “ssoossh ssh config”Prints the ssh_config recipes that make ssh invoke ssoossh, with the rules
that decide which one you want. It contacts nothing and reads nothing but that
text, so it answers before a server is configured and keeps answering after one
stops responding – which is exactly when you go looking for it.
No flags beyond the global ones.
ssoossh ssh configIt does not report resolved settings. --debug is the one place those are
printed, so there is no second version of the truth to keep in step. See
ssh_config integration for the long form.
ssoossh ssh proxycommand
Section titled “ssoossh ssh proxycommand”For use as ssh_config’s ProxyCommand. It ensures a valid certificate, then
relays stdio to the target host. The arguments after it mirror exactly what you
would have written without ssoossh.
No flags beyond the global ones; everything after the command name is the relay
command and its arguments. The relay is found on PATH, as ssh would find
it, so nc works as well as /usr/bin/nc.
On Linux and macOS ssoossh replaces itself with the relay once the certificate is in place. Windows cannot do that, so there ssoossh starts the relay with its own stdin and stdout and stays running as its parent until the connection ends.
# beforeProxyCommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %p# afterProxyCommand ssoossh ssh proxycommand /usr/bin/nc -X connect -x 192.0.2.0:8080 %h %pssoossh ssh inspect
Section titled “ssoossh ssh inspect”Shows what each certificate ssoossh is holding actually grants, rather than the certificate blob, which tells a human nothing.
No flags beyond the global ones.
ssoossh ssh inspectThe report opens with Storage, naming where the certificates are kept: an
ssh-agent holds them in a process, and a file backend adds a Key files list of
the paths on disk (private key, public key, certificate) so you know which files
the certificates below came out of.
Each certificate then prints as Principals, Key ID, Type, Expires,
Serial, Extensions, and Critical options. With none loaded it says so,
naming the storage backend it looked in.
ssoossh ca
Section titled “ssoossh ca”Retrieves the CA public key of the configured server. This is what target hosts must trust.
No flags beyond the global ones.
ssoossh --server https://ssh.example.com ca > /etc/ssh/ssoossh_ca.pubThen on each target host:
TrustedUserCAKeys /etc/ssh/ssoossh_ca.pubFetching the key from the running server confirms the deployed key rather than trusting a local copy blindly. Trusting the CA in sshd covers the host side.
ssoossh host
Section titled “ssoossh host”Configures the principal mapping used when sshd asks for authorized
principals via AuthorizedPrincipalsCommand, and checks that sshd will accept
ssoossh certificates. Only host check talks to the server, and only to fetch
the CA keys it compares the host’s against.
| Flag | Default | What it does |
|---|---|---|
--file <path> |
/etc/ssoossh/principals.yaml |
The local principal mapping file: YAML listing, per local account, the principals allowed to assume it |
--file is inherited by every host subcommand.
ssoossh host principals
Section titled “ssoossh host principals”Implements AuthorizedPrincipalsCommand. It is called on every login attempt
and never touches the network – it answers only from the local mapping file.
It expects one argument, the local username to look up, and prints one
principal per line.
The looked-up name is always among them. The mapping file is additive: it
enriches the set of names allowed to assume an account, and it can never take
the account’s own name away – not by omission, and not by listing the account
with no principals. That is also what sshd accepts unaided, since with no
AuthorizedPrincipalsCommand configured it admits a certificate carrying the
target account name.
| Situation | Behavior |
|---|---|
| Account found | Prints its principals in file order, then the account name if the file did not already list it, exit 0 |
| Unknown account, or missing file | Prints the account name alone, exit 0 |
| Unreadable or malformed file | Prints the account name alone, exit 0, and logs the failure to stderr |
| Client configuration fails to load | Answers as above and warns on stderr, since it reads no setting; a --config file that is missing or malformed still fails it, exit 1 |
A file that will not load is reported rather than refused. pam_ssoossh treats
a map it cannot read as no map at all and falls back to the same rule, and one
file must not mean two policies – so this host stays consistent, and the
broken file is made loud in the log rather than in a denied login. The
diagnostic goes to stderr because sshd parses stdout as the principal list.
It needs no privilege beyond read access to the mapping file, so run it as a dedicated unprivileged account rather than as root:
AuthorizedPrincipalsCommand /usr/bin/ssoossh host principals %uAuthorizedPrincipalsCommandUser ssoossh-principalsSee trusting the CA in sshd for creating that account and the file permissions it needs.
ssoossh host mapping
Section titled “ssoossh host mapping”Manages that same file.
| Command | Arguments | What it does |
|---|---|---|
host mapping list |
none | Print the current mapping |
host mapping add |
<account> <principal> |
Add a principal to the account, deduplicating; the principal’s syntax is validated before anything is written |
host mapping remove |
<account> <principal> |
Remove that principal from the account (a no-op if it is not present) |
host mapping remove |
<account> |
Remove the entire account mapping |
sudo ssoossh host mapping add deploy alice@example.comsudo ssoossh host mapping listsudo ssoossh host mapping remove deploy alice@example.comssoossh host check
Section titled “ssoossh host check”Reports whether this host’s sshd will accept ssoossh certificates. Run it as
root after setting a host up, and from configuration management after every
change: it exits non-zero when any check fails.
sudo ssoossh host checksudo ssoossh host check --user deploy --addr 10.0.0.5It reads sshd’s own effective configuration (sshd -T), so Include order,
built-in defaults and, with --user, Match blocks are resolved by sshd
itself rather than by a parser that could disagree with it. It is read-only: it
changes no file and reloads nothing.
| Flag | Default | What it does |
|---|---|---|
--user <account> |
none | Apply sshd’s Match blocks for this account, and list the principals that may log in as it |
--addr <address> |
none | Apply Match blocks for this source address |
--sshd <path> |
sshd on PATH, then /usr/sbin/sshd |
The sshd to ask |
| Check | Fails when |
|---|---|
pubkey-auth |
PubkeyAuthentication is off. A certificate login is public key authentication. |
trusted-ca |
TrustedUserCAKeys is none, unreadable, or holds no key. sshd then refuses every certificate and logs only Failed publickey. |
ca-match |
The host trusts none of the CA keys the server signs with. Missing only some of them is a warning: a rotation in progress. |
ca-signature |
CASignatureAlgorithms does not allow the algorithm the CA signs with, as under a FIPS policy that drops ssh-ed25519 |
cert-types |
PubkeyAcceptedAlgorithms allows no certificate type the client generates. Refusing only some is a warning. |
principals-command |
AuthorizedPrincipalsCommand is relative, or its resolved file or any directory above it is not root-owned or is group- or world-writable, so sshd refuses to run it |
principals-user |
AuthorizedPrincipalsCommandUser is unset or does not exist |
principals |
The command line passes no %u |
principals-mapping |
The mapping file exists but will not load |
mapping-access |
The command’s account cannot read the mapping file |
The rest are notes or warnings and never fail the run: TrustedUserCAKeys
writable by someone other than root; an AuthorizedPrincipalsCommand naming the
/usr/local/bin/ssoossh compatibility link, which sshd follows to
/usr/bin/ssoossh and runs until the link is removed; plain public keys still
accepted beside certificates (plain-keys asks whether that is intended; it is
how the docs suggest adopting ssoossh); and a clock that is not synchronized.
The CA keys to compare with come from a pinned capubkey when there is one,
otherwise from the server, never from the CA cache. When neither is available
ca-match is a warning and every other check still runs: the local findings do
not depend on reaching the server, or on an ssh-agent.
ssoossh service enroll
Section titled “ssoossh service enroll”Enrolls a keypair, bound by the server to an enrollment code, for later unattended certificate retrieval. The keypair is either generated here or already present on disk.
| Flag | Default | What it does |
|---|---|---|
--key <path> |
none, required | Keypair path, relative or absolute. Generates both files if neither <path> nor <path>.pub exists; enrolls the existing pair if both do; refuses if only one does |
--retrieve |
off | Immediately redeem the code once and write the certificate to <path>-cert.pub |
--extensions <list> |
none | Certificate extensions to request, comma-separated. The approver sees them and can change the set |
ssoossh service enroll --key /etc/backup/id --retrievessoossh service enroll --key /etc/backup/id --extensions permit-ptyNothing is requested by default, which is the right posture for an unattended
account: a job that needs no agent forwarding should not hold the permission
to do it. What this flag sends is a request – the approver sees it, may
change it, and the server bounds the result by
cert_options.service.extensions
either way, so it cannot obtain anything the deployment has not permitted.
ssoossh service retrieve
Section titled “ssoossh service retrieve”Redeems an enrollment code, writing the certificate to <path>-cert.pub and
checking local disk first to avoid unnecessary server calls.
| Flag | Default | What it does |
|---|---|---|
--code <code> |
none, required | The enrollment code to redeem |
--key <path> |
none, required | Keypair path; the certificate lands at <path>-cert.pub |
--grace <duration> |
1m |
How much validity a certificate on disk must still have before it counts as fresh, for example 30s, 5m, 1h |
--force |
off | Retrieve a new certificate even if a valid one exists on disk |
ssoossh service retrieve --code K7M4QP2X --key /etc/backup/idBoth service commands are covered in full, with worked examples, on Service accounts.
ssoossh version
Section titled “ssoossh version”Prints version, commit, build info, and the platform (linux/amd64).
Offline: it makes no network call. ssoossh --version prints the same line.
ssoossh versionssoossh --versionssoossh version --jsonWith --json it prints the same values as an object (including os and
arch), plus the list of command paths this build implements. That list is
the supported way for a deployment tool to tell releases apart: probing
--help output breaks on wording no release promises to keep.
Shell completion
Section titled “Shell completion”ssoossh completion <shell> prints a completion script for bash, zsh,
fish, or powershell. ssoossh completion <shell> --help says where to put
it. For example, for bash:
ssoossh completion bash | sudo tee /etc/bash_completion.d/ssoossh >/dev/nullThe packages do not install a completion script, so this is a one-time step per machine.
Where to go next
Section titled “Where to go next”- ssh_config integration – the two ways
sshcan invoke this client. - Client configuration – the
ssoossh.yamlfile and where each setting comes from. - ssoossh.yaml reference – every key, type, and default.
- Diagnostics –
-v,--debug, and what to attach to a bug report.