nss
Serves POSIX accounts and groups from the directory to the ssoossh-nss daemon on each host, authenticated by fleet API keys. Disabled by default.
Every account and group comes from the directory, people and shared or service accounts alike, so NSS requires ldap.enabled; there is no OIDC claim source for POSIX attributes. The directory connection, base DN and ldap.id_attribute are the ldap block’s.
enabled
Section titled “enabled”bool, default false
Turns the NSS directory on: the lookup endpoints, the fleet key administration and the directory sync of POSIX entries. Requires ldap.enabled; a configuration with this on and LDAP off fails at startup.
nss: enabled: falseuser_filter
Section titled “user_filter”string, default (objectClass=posixAccount)
The LDAP filter that selects POSIX accounts under ldap.base_dn. A plain RFC 4515 filter in parentheses, not a template: the sync enumerates it with paged searches, so ldap.limits does not cap it, and an on-demand lookup ANDs it with an equality on the name or uid attribute. Required when nss.enabled is on; its syntax is checked when the server starts. A preset from ldap.schema may set this.
nss: user_filter: "(objectClass=posixAccount)"group_filter
Section titled “group_filter”string, default (objectClass=posixGroup)
The LDAP filter that selects POSIX groups under ldap.base_dn, used the same way as user_filter. Required when nss.enabled is on. A preset from ldap.schema may set this.
nss: group_filter: "(objectClass=posixGroup)"disabled_filter
Section titled “disabled_filter”string, default empty
An LDAP filter an account’s entry is tested against on every read: a match marks the account disabled by the directory itself, which hosts then lock. For example (nsAccountLock=TRUE) on 389-ds and FreeIPA, or (userAccountControl:1.2.840.113556.1.4.803:=2) on Active Directory. Empty means the directory never disables an account; a person’s ssoossh disable still does. A preset from ldap.schema may set this.
nss: disabled_filter: "(nsAccountLock=TRUE)"sync_interval
Section titled “sync_interval”duration, default 15m
How often the incremental sync runs: it reads only the accounts and groups whose modifyTimestamp is no older than five minutes before the last successful run on this instance began, so changes reach hosts within one interval. The first run after a start, and any run the directory refuses the modifyTimestamp filter for, is a full sync instead. Every instance runs its own. Zero disables the incremental sync.
nss: sync_interval: 15mfull_sync_interval
Section titled “full_sync_interval”duration, default 24h
How often the full sync runs: it reads every account and group the filters select, which is the only run that notices an entry has gone (missing_since, then a tombstone after tombstone_after) and the only one that clears collisions whose other entry has gone. POST /api/admin/ldap/sync runs one too. Zero disables the scheduled full sync.
nss: full_sync_interval: 24hgecos_template
Section titled “gecos_template”string, default {{.DisplayName}}
Renders the passwd gecos field, with the same text/template engine as the key ID templates. It sees .Name (the mapped name), .DisplayName (the first non-empty attribute of attributes.gecos_attributes, else .Name) and .Attr.<name> for an attribute listed in attributes.gecos_attributes; nothing else is reachable, and an unlisted attribute renders empty. A multi-valued attribute renders with join, as in {{join .Attr.mail “, “}}.
The result is cleaned before any host sees it: invalid UTF-8 becomes .Name, control characters and “:” become spaces, whitespace is collapsed and trimmed, the value is capped at 256 bytes, and an empty result becomes .Name. A template that does not parse, or that names a field which does not exist, fails startup.
nss: gecos_template: "{{.DisplayName}}"auto_private_groups
Section titled “auto_private_groups”string, default hybrid
Chooses each account’s primary group, with the names and meanings of sssd’s option (decided 2026-10-18 by the owner: match sssd):
“hybrid”: the directory’s gid. An account whose uid equals its gid, when no directory group holds that gid, gets a private group named after it; a directory group that does hold it is the primary group. An entry without the gid attribute is skipped with a warning.
“true”: every account gets a private group with gid equal to its uid, and the gid attribute is optional. A gid attribute other than the uid is served as a supplementary group when a directory group holds it, and follows the directory without waiting for an admin. An account whose uid is a directory group’s gid, or whose name is a directory group’s name, is not served (sssd refuses whichever of the two it caches second; here the directory group always wins).
“false”: the directory’s gid, no private groups. A gid no directory group holds is still served; it just does not resolve to a name. An entry without the gid attribute is skipped with a warning.
Applied by the server when an account is read, so every host sees the same gid; there is no host-side setting. An account stored without a gid under “true” is not served after a switch to the other modes, which have no primary gid to give it.
nss: auto_private_groups: "hybrid"tombstone_after
Section titled “tombstone_after”duration, default 168h
How long an entry may stay missing from the directory before its account or group becomes deleted. Measured from the first successful sync that could not find it by id, DN or filter; a directory outage is never a miss. A deleted group still resolves by name and gid, so ls -l keeps showing a name, but is served with no members, so it grants nothing. Zero tombstones an entry at the first sync that misses it.
nss: tombstone_after: 168htombstone_retention
Section titled “tombstone_retention”duration, default 2160h
How long a deleted account or group stays resolvable (an account served as disabled, a group with no members) before it is purged and answers not found. A tombstone holds its number and name the whole time, so neither can be handed to a new entry, and the files it owned on hosts cannot pass to someone else. Zero purges a tombstone at the next sweep and frees its number and name at once.
nss: tombstone_retention: 2160hdefault_home
Section titled “default_home”string, default /home/%u
The home directory served for an account whose entry has no home attribute; %u is replaced by the account’s name. Must be an absolute path when nss.enabled is on.
nss: default_home: "/home/%u"default_shell
Section titled “default_shell”string, default empty
The shell served for an account whose entry has no shell attribute. Empty serves no shell, and the host applies its own default.
nss: default_shell: "/bin/bash"disabled_shell
Section titled “disabled_shell”string, default /usr/sbin/nologin
Replaces the shell of every disabled or deleted account, so a locked account cannot run a login shell even where a host ignores the lock. Must be an absolute path when nss.enabled is on.
nss: disabled_shell: "/usr/sbin/nologin"max_group_members
Section titled “max_group_members”int, default 2000
Caps the members returned for one group. A larger group is truncated and flagged as truncated in the response, and the daemon logs it. The sync stores every member it can resolve to an account; this caps only what one lookup returns. Must be greater than zero.
nss: max_group_members: 2000rate_limit
Section titled “rate_limit”number, default 20
The lookups per second allowed for one fleet key from one source address. The address is the one the server observes, honouring forwarded headers only from http.trusted_proxies, the same address the audit log records as source_ip; behind a load balancer listed there each host keeps its own bucket rather than all of them sharing the balancer’s. An overbroad http.trusted_proxies lets a key holder spoof that address with X-Forwarded-For and get a fresh bucket per address; nss.key_source_alert still fires but never blocks. Each server instance keeps its own buckets, so N instances behind a load balancer allow N times this. Must be greater than zero.
nss: rate_limit: 20rate_burst
Section titled “rate_burst”int, default 200
How many lookups one key and source address (as for rate_limit, with the same http.trusted_proxies caveat) may make back to back before rate_limit starts holding them back: a host starting up resolves many names at once. Must be greater than zero, since a zero burst refuses every lookup.
nss: rate_burst: 200miss_alert_rate
Section titled “miss_alert_rate”number, default 5
The not-found lookups per second for one key above which the server raises an alert (a log line and an audit event). It never blocks anything: a host enumerating names it does not know is worth hearing about, not refusing. Zero disables the alert.
nss: miss_alert_rate: 5usage_retention
Section titled “usage_retention”duration, default 2160h
How long the per-key, per-address, per-day usage counts are kept for the usage and rotation reports. Zero disables the prune and keeps every row.
nss: usage_retention: 2160hkey_max_lifetime
Section titled “key_max_lifetime”duration, default 8760h
The longest a new fleet key may live, and how long it lives when its creator gives no expiry. A later expiry is trimmed to it, and each rotation renews a key by its own lifetime up to it. Changing this does not touch existing keys until their next rotation. 0 sets no limit: a key created without an expiry then never expires.
nss: key_max_lifetime: 8760hkey_rotation_grace
Section titled “key_rotation_grace”duration, default 720h
How long the previous secret stays accepted after a key is rotated, so every host can pick up the new one before the old one stops working. Zero ends the previous secret at the rotation itself.
nss: key_rotation_grace: 720hsource_allow_list
Section titled “source_allow_list”list, default empty
Limits the lookup endpoints to requests from these CIDR networks, checked before the key is: a request from anywhere else is refused with an audit event that carries its address and the key id it presented. The address is the one the server observes, honouring forwarded headers only from http.trusted_proxies, the same address the audit log records as source_ip; a forwarded header from any other peer is ignored. An overbroad http.trusted_proxies lets a key holder pass this list, and forge the audited address, with X-Forwarded-For. Empty allows every address.
nss: source_allow_list: []privileged_name_alert
Section titled “privileged_name_alert”list, default root, admin, daemon, bin, sys
Lists account names whose lookup raises an audit alert, because a directory entry that answers for one of them could shadow a host’s own system account. Empty disables the alert.
nss: privileged_name_alert: [root, admin, daemon, bin, sys]key_source_alert
Section titled “key_source_alert”int, default 1000
The number of distinct source addresses one key may be seen from in a day before the server raises an audit alert: far more than a fleet’s size suggests the key has leaked. Zero disables the alert.
nss: key_source_alert: 1000