Skip to content

ssoossh.yaml reference

Every setting in the client’s ssoossh.yaml, grouped as the file itself groups them. Only server has no working default, so a usable file can be one line.

For where the file is looked for, how several of them combine, and which source wins, see Client configuration. The same content ships as the ssoossh.yaml(5) man page and as the annotated /etc/ssoossh/ssoossh.yaml installed by the .deb and .rpm packages.

Key Type Default
server string empty
capubkey string or list empty
insecure_skip_verify bool false
request_timeout duration 2m

string, default empty

Base URL of the ssoosshd server, including the scheme. If the scheme is omitted, https is assumed. There is no default, and every command that talks to the server fails without it. --server overrides it for one invocation.

server: "https://ssh.example.com"

string or list of strings, default empty

The server’s CA public key, in authorized_keys format. When set, the client skips asking the server for the CA key entirely, which pins the key rather than trusting a fetched one, and is the only form reported to the server as a trusted CA so an approval page can warn before this client refuses a certificate.

capubkey: "ecdsa-sha2-nistp384 AAAAE2VjZHNh... ssoossh-ca"

A list holds more than one, which is what a CA rotation needs: both keys are live at once while the old one ages out, and a client trusting only one would refuse half the certificates issued in between.

capubkey:
- "ecdsa-sha2-nistp384 AAAAE2VjZHNh... ssoossh-ca-old"
- "ecdsa-sha2-nistp384 AAAAE2VjZHNh... ssoossh-ca-new"

When empty, the client fetches the key from the server and caches it, so later commands neither pay a round trip nor fail while the server is restarting. See the CA key cache.

With no capubkey set, the client stores the keys it fetched and reuses them for a day before asking again. This is what keeps a client working while the server is down: an already-valid certificate is reused without any network call, where before the client failed at startup fetching a key it already had.

Platform Path
Linux, macOS $XDG_CACHE_HOME/ssoossh/ca.json, else ~/.cache/ssoossh/ca.json
Windows %LocalAppData%\ssoossh\ca.json

Deliberately not the configuration file. The per-user config outranks the system one, so a cached key written there would silently shadow a capubkey an administrator set in /etc/ssoossh/ssoossh.yaml afterwards.

A refresh that fails changes nothing: the cached keys stay in use and the command carries on. A refresh with something already cached is given two seconds, because the client runs from Match exec with ssh waiting on it.

It is a cache, not a trust decision. The keys are used only to recognise this client’s own certificates, never to verify a host, and they are never reported to the server as pinned. If the server’s key set is ever replaced outright the client adopts the new one and warns, since it cannot tell a rotation it slept through from a server rebuilt around a new CA. Set capubkey to refuse a change instead of adopting it.

bool, default false

Skip TLS certificate verification when talking to server. For development against a self-signed certificate only; it defeats the point of pinning capubkey above.

insecure_skip_verify: false

duration, default 2m

The longest one ordinary call to the server may take, from connect to the last byte of the answer. Without it, a server that accepts the connection and never answers would hang the client, and under Match exec that hangs ssh. It does not limit the wait for a browser approval, which the server bounds with its own cert_options.client_timeout.

A service certificate retrieval waits on signing, which the server bounds at a tenth of cert_options.client_timeout (30 seconds with the server’s default of 5 minutes). Raise request_timeout if that server setting is above 20 minutes. Zero and negative values are refused.

request_timeout: 2m
Key Type Default
use_agent bool true
fallback_file_agent bool true
key_filename string id_ssoossh

bool, default true

Keep keys and certificates in a running ssh-agent rather than in files. This is the recommended mode, and the only mode ssoossh ssh proxycommand supports: ssh reads key files once at startup and never sees a certificate written after that.

Setting it to false means the agent is not consulted at all, not merely deprioritized – keys and certificates always go to the files named by key_filename.

use_agent: true

bool, default true

What to do when an agent was wanted but none could be reached: fall back to key files (true), or fail the command (false). It has no effect when use_agent is false, since file storage is already in use in that case.

--debug reports both the preference and the backend that actually resolved, so a use_agent: true that ended up on files is visible rather than silent.

fallback_file_agent: true

string, default id_ssoossh

Base name (or path) for the key and certificate files, used when use_agent is false or when the fallback above took effect. A bare name resolves inside ~/.ssh, a ~/... path is expanded, and an absolute path is used as given. The public key and certificate are written beside it as <name>.pub and <name>-cert.pub.

key_filename: id_ssoossh

A fresh keypair is generated for every certificate request, so this is not a long-lived identity file. Both sshkey sub-keys are optional.

Key Type Default
sshkey.type string ecdsa
sshkey.size int 0 (per-algorithm default)
fips bool unset

string, default ecdsa

The key algorithm: ed25519, ecdsa, or rsa. The default is ECDSA P-384 unconditionally, whether or not FIPS steering is in effect. --key-type overrides it for ssoossh ssh login.

ed25519 stays selectable but is not the default: it only entered FIPS 186-5 in 2023 and several FIPS policies still reject it outright. While FIPS steering is in effect, choosing an algorithm that is not FIPS-approved (ecdsa and rsa are the approved ones) is a hard error at config-load time, not a warning. The way around it is to disable fips, not to pick a different type while it stays on.

sshkey:
type: ecdsa

int, default 0 (per-algorithm default)

What this means depends on type:

type size means Accepted Default
ed25519 nothing; it has one size – ignored, and a nonzero value produces a warning
ecdsa the NIST curve 256, 384, 521 384
rsa the modulus in bits at least 2048 3072

RSA key generation costs on the order of hundreds of milliseconds and is highly variable; ecdsa and ed25519 are effectively instant. Since a fresh key is generated on every certificate request, that cost is paid every time rather than once. --key-size overrides this for ssoossh ssh login.

sshkey:
size: 384

bool, default unset

Steers key generation toward algorithms that SSH implementations running in FIPS mode accept. When in effect, a non-approved sshkey.type is a hard error at config-load time.

Left unset deliberately, in which case it follows whether the running binary is itself in Go’s FIPS 140-3 mode. Set it explicitly to target a FIPS-mode server from a client that is not itself in FIPS mode, or to false as the escape hatch – unless a system enforce file locks fips: true, which wins regardless.

This setting only affects the client’s own algorithm checks. Unlike the server, there is no per-install hook here that also sets GODEBUG=fips140=only in the binary’s environment; an operator wanting runtime-layer enforcement beneath these checks sets it themselves, in the shell profile or wrapper that invokes ssoossh.

fips: true
Key Type Default
certificate_extensions.no_pty bool false
certificate_extensions.no_agent_forwarding bool false
certificate_extensions.no_port_forwarding bool false
certificate_extensions.no_x11_forwarding bool false
certificate_extensions.no_user_rc bool false

ssoossh ssh login requests the full interactive extension set by default: permit-pty, permit-agent-forwarding, permit-port-forwarding, permit-X11-forwarding, and permit-user-rc. Each key below is an opt-out from that set: false (the default) requests the extension, true does not.

The effective set is the default, minus these config opt-outs, minus the matching --no-* flags, minus anything platform-native policy forbids – in that order. A flag cannot re-add what policy forbids.

Requesting the full set is always safe: the server narrows the request against its own configuration before signing, and the approval page shows what survived. Requesting nothing is not useful, because narrowing is an intersection – an empty request yields a certificate carrying no extensions at all, which cannot open an interactive session.

certificate_extensions:
no_pty: false
no_agent_forwarding: false
no_port_forwarding: false
no_x11_forwarding: false
no_user_rc: false

bool, default false

Do not request permit-pty. Without that extension the certificate cannot open an interactive terminal. Overridden by --no-pty.

certificate_extensions:
no_pty: false

certificate_extensions.no_agent_forwarding

Section titled “certificate_extensions.no_agent_forwarding”

bool, default false

Do not request permit-agent-forwarding. Overridden by --no-agent-forwarding.

certificate_extensions:
no_agent_forwarding: false

bool, default false

Do not request permit-port-forwarding. Overridden by --no-port-forwarding.

certificate_extensions:
no_port_forwarding: false

bool, default false

Do not request permit-X11-forwarding. Overridden by --no-x11-forwarding.

certificate_extensions:
no_x11_forwarding: false

bool, default false

Do not request permit-user-rc, which is what lets ~/.ssh/rc run on login. Overridden by --no-user-rc.

certificate_extensions:
no_user_rc: false

Browser, administration, and reserved keys

Section titled “Browser, administration, and reserved keys”
Key Type Default
try_open_browser bool false
enforce string empty
username string empty

bool, default false

Make a best-effort attempt to launch the system browser at the approval URL during ssoossh ssh login. Strictly best-effort: the URL is always printed first, so a headless machine with no browser can still complete a login by hand, and a launch failure is reported and otherwise ignored.

try_open_browser: true

string, default empty

Names another YAML file whose settings a user cannot override: it is merged after the per-user file and --config.

Only honored when read from the machine-wide file (/etc/ssoossh/ssoossh.yaml, or %ProgramData%\ssoossh\ssoossh.yaml on Windows). A bare filename resolves next to that file, so naming one cannot reach a file the user controls. Setting enforce anywhere else has no special effect. A missing or malformed target is a hard startup error, unlike the optional files above.

A guardrail, not a security boundary: the client runs as the user, who can always supply their own binary. The one limit enforced beyond client cooperation is cert_options.*.valid_duration on the server. Windows and macOS can lock the same settings through Group Policy and managed preferences instead – see Client settings enforcement.

# /etc/ssoossh/ssoossh.yaml only
enforce: ssoossh-locked.yaml

string, default empty

Present in the schema and read by nothing. It was intended to name a service account, but that is chosen by the approver in the web UI instead: enrollment requests are unauthenticated, so the client has no session against which to validate one. Setting it changes nothing.

#username: # has no effect