nslcd.conf(5)

πŸ“¦
version 0.9.13 Β· 4 versions
, in arch rolling, debian trixie, nixos 26.05, nixpkgs unstable, ubuntu questing, ubuntu resolute, ubuntu stonking

✨ nslcd.conf(5) ✨ β€” the glow-up guide to your LDAP nameservice daemon config πŸ’–

okay bestie, listen up, this is from the System Manager's Manual and it's literally the manual page for nslcd.conf(5), and it's giving essential reading, fr fr.


🌸 NAME 🌸

nslcd.conf β€” the configuration file for the LDAP nameservice daemon 🧚


πŸ’… DESCRIPTION πŸ’…

so the nss-pam-ldapd package lets LDAP directory servers be your primary source of name service information. (and like, name service info is normally users, hosts, groups, and all that other data that historically lived in flat files or NIS, iykyk.)

the file nslcd.conf holds all the configuration info for running nslcd (go peek at nslcd(8) if you want). it's got options, one on each line, and they define the way NSS lookups and PAM actions get mapped to LDAP lookups. slay. πŸŽ€


πŸ‘‘ OPTIONS πŸ‘‘

🌈 RUNTIME OPTIONS 🌈

  • threads NUM β€” tells it how many threads to start, and those threads handle requests and do the LDAP queries. lowkey important: each thread opens a separate connection to the LDAP server. the default is to start 5 threads. πŸ’«
  • uid UID β€” the user id the daemon should run as. can be a numerical id or a symbolic value. if you don't specify a uid, no attempt to change the user gets made, periodt. heads up tho: use values that don't need LDAP to resolve. 🫢
  • gid GID β€” the group id the daemon should run as. also can be a numerical id or a symbolic value. if no gid is specified, no attempt to change the group happens. same note as above: use values that don't need LDAP to resolve. πŸ’œ
  • log SCHEME [LEVEL] β€” controls how logging gets done. the SCHEME argument can be none, syslog, or an absolute file name. the LEVEL argument is optional and sets the log level. the log level can be one of: crit, error, warning, notice, info or debug. the default log level is info. all messages at the specified loglevel or higher get logged. you can supply this option multiple times. if you omit it entirely, syslog info is assumed. ✨

πŸ¦‹ GENERAL CONNECTION OPTIONS πŸ¦‹

  • uri URI ... β€” the LDAP URI of the server to connect to. the URI scheme can be ldap, ldapi or ldaps, which specify LDAP over TCP, ICP or SSL respectively (if your LDAP library supports it, that is).

alternatively, the value DNS can be used to try looking up the server using DNS SRV records. by default the current domain is used, but you can query another domain with the DNS:DOMAIN syntax. to convert SRV records for port 389 into an ldaps:// URI, DNSLDAPS can be used.

when you're using the ldapi scheme, %2f should be used to escape slashes (like ldapi://%2fvar%2frun%2fslapd%2fldapi/), although most of the time this shouldn't be needed.

this option may be specified multiple times and/or with more URIs on the line, separated by spaces. normally, only the first server gets used, with the following servers as fall-back (see bind_timelimit below πŸ‘‡).

if LDAP lookups are used for host name resolution, any host names should be specified as an IP address or a name that can be resolved without using LDAP. no cap, this matters. 🚨
  • ldap_version VERSION β€” the version of the LDAP protocol to use. the default is to use the maximum version supported by the LDAP library. πŸ”₯
  • binddn DN β€” the distinguished name to bind to the directory server with for lookups. the default is to bind anonymously. πŸ™ˆ
  • bindpw PASSWORD β€” the credentials to bind with. only applicable when used with binddn above. if you set this one, you should consider changing the permissions of the nslcd.conf file to only grant access to the root user. πŸ”
  • rootpwmoddn DN β€” the distinguished name to use when the root user tries to modify a user's password using the PAM module.
note that currently this DN needs to exist as a real entry in the LDAP directory. it's not a vibe-only situation.
  • rootpwmodpw PASSWORD β€” the credentials to bind with if the root user tries to change a user's password. only applicable when used with rootpwmoddn above. if you don't specify this option, the PAM module prompts the user for this password instead. and if you do set it, you should consider changing the permissions of the nslcd.conf file to only grant access to the root user. πŸ’–

πŸŽ€ SASL AUTHENTICATION OPTIONS πŸŽ€

  • sasl_mech MECHANISM β€” the SASL mechanism to use when performing SASL authentication.
  • sasl_realm REALM β€” the SASL realm to use when performing SASL authentication.
  • sasl_authcid AUTHCID β€” the authentication identity to use when performing SASL authentication.
  • sasl_authzid AUTHZID β€” the authorization identity to use when performing SASL authentication. must be specified in one of the formats: dn:<distinguished name> or u:<username>. don't freestyle this one bestie. ✍️
  • sasl_secprops PROPERTIES β€” the Cyrus SASL security properties. all the allowed values are described in the ldap.conf(5) manual page, go check it.
  • sasl_canonicalize yes|no β€” decides whether the LDAP server host name should be canonicalised. if this is set to yes, the LDAP library will do a reverse host name lookup. by default, it's left up to the LDAP library whether this check is performed or not. main character energy: deferred. ✨

πŸ’œ KERBEROS AUTHENTICATION OPTIONS πŸ’œ

  • krb5_ccname NAME β€” sets the name for the GSS-API Kerberos credentials cache.

πŸ“ SEARCH/MAPPING OPTIONS πŸ“

  • base [MAP] DN β€” the distinguished name (DN) to use as the search base. you can supply this option multiple times and all the specified bases will be searched. πŸ”

you can specify a global search base or a MAP-specific one. if no MAP-specific search bases are defined, the global ones get used.

if, instead of a DN, you specify the value DOMAIN, the host's DNS domain is used to construct a search base. a value of "" can be used to indicate an empty search base (quotes are not otherwise supported for base values, and not all LDAP server configurations support this either).

if this value isn't defined, an attempt is made to look it up in the configured LDAP server. and if the LDAP server is unavailable during start-up, nslcd will not start. πŸ’€

  • scope [MAP] sub[tree]|one[level]|base|children β€” the search scope (subtree, onelevel, base or children). the default scope is subtree; base scope is almost never useful for name service lookups; children scope is not supported on all servers.
  • deref never|searching|finding|always β€” the policy for dereferencing aliases. the default policy is to never dereference aliases.
  • referrals yes|no β€” whether automatic referral chasing should be enabled. the default behaviour is to chase referrals.
  • filter MAP FILTER β€” the FILTER is an LDAP search filter to use for a specific map. the default filter is a basic search on the objectClass for the map (like (objectClass=posixAccount)).
  • map MAP ATTRIBUTE NEWATTRIBUTE β€” this one lets you look up custom attributes instead of the default RFC 2307 attributes. the MAP can be one of the supported maps listed below. the ATTRIBUTE is the one used in RFC 2307 (like userPassword, ipProtocolNumber, macAddress, etc.).

the NEWATTRIBUTE can be the name of any attribute as it's available in the directory.

if the NEWATTRIBUTE is quoted (") as "EXPRESSION", it's treated as an expression that gets evaluated to build up the actual value used. see the section on attribute mapping expressions below for more details. 🧠

only some attributes for group, passwd and shadow entries can be mapped with an expression (because other attributes may be used in search filters). for group entries, only the userPassword attribute may be mapped with an expression. for passwd entries, these attributes may be mapped with an expression: userPassword, gidNumber, gecos, homeDirectory and loginShell. for shadow entries, these may be mapped with an expression: userPassword, shadowLastChange, shadowMin, shadowMax, shadowWarning, shadowInactive, shadowExpire and shadowFlag.

the uidNumber and gidNumber attributes in the passwd and group maps may be mapped to the objectSid followed by the domain SID, to derive numeric user and group ids from the SID (like objectSid:S-1-5-21-3623811015-3361044348-30300820).

by default, all userPassword attributes are mapped to the unmatchable password ("*") to avoid accidentally leaking password information. we love a security queen. πŸ‘‘

⏰ TIMING/RECONNECT OPTIONS ⏰

  • bind_timelimit SECONDS β€” the time limit (in seconds) to use when connecting to the directory server. this is distinct from the time limit specified in timelimit, and it only affects the set-up of the connection. note that not all LDAP client libraries support setting the connection time out. the default bind_timelimit is 10 seconds.
  • timelimit SECONDS β€” the time limit (in seconds) to wait for a response from the LDAP server. a value of zero (0), which is the default, means wait indefinitely for searches to be completed. no rush, no stress. 😌
  • idle_timelimit SECONDS β€” the period of inactivity (in seconds) after which the connection to the LDAP server gets closed. the default is not to time out connections.
  • reconnect_sleeptime SECONDS β€” the number of seconds to sleep when connecting to all LDAP servers fails. by default, 1 second is waited between the first failure and the first retry.
  • reconnect_retrytime SECONDS β€” the time after which the LDAP server is considered to be permanently unavailable. once this time is reached, retries are only done once per this time period. the default value is 10 seconds.

note that the reconnect logic described above is the mechanism used between nslcd and the LDAP server. the mechanism between the NSS and PAM client libraries on one end and nslcd on the other is simpler, with a fixed compiled-in time out of 10 seconds for writing to nslcd and a time out of 60 seconds for reading answers. nslcd itself has a read time out of 0.5 seconds and a write time out of 60 seconds. ✨ (yes bestie, the numbers are exact, don't round them πŸ’…)

πŸ’… SSL/TLS OPTIONS πŸ’…

okay bestie, this is the section where we make your LDAP connection stop being naked on the wire. very important, no cap.

  • ssl on|off|start_tls β€” says whether we're doing SSL/TLS or not (and ngl, the default is not doing it). If you say start_tls then StartTLS gets used instead of raw LDAP-over-SSL. Heads up though: not all LDAP client libraries support both SSL, StartTLS and all the related config options, so like, know your lib.
  • tls_reqcert never|allow|try|demand|hard β€” tells nslcd what checks to run on the certificate the server hands you. The vibes of each value are explained over in the ldap.conf(5) manual page. πŸŽ€ If peer verification is enabled, you need at least one of tls_cacertdir and tls_cacertfile, fr fr.
  • tls_cacertdir PATH β€” the directory holding X.509 certificates for peer authentication. ⚠️ This parameter is ignored when using GnuTLS β€” and on Debian, OpenLDAP is linked against GnuTLS, so yeah. πŸ™ˆ
  • tls_cacertfile PATH β€” the path to the X.509 certificate used for peer authentication. ✨
  • tls_randfile PATH β€” the path to an entropy source. Also ignored when using GnuTLS, and on Debian OpenLDAP is linked against GnuTLS. πŸ’€
  • tls_ciphers CIPHERS β€” the ciphers to use for TLS. Go read your TLS implementation's documentation for the details, that's a whole other rabbit hole bestie.
  • tls_cert PATH β€” the path to the file with the local certificate for client TLS authentication. πŸ’–
  • tls_key PATH β€” the path to the file with the private key for client TLS authentication. Keep this one safe, obviously. πŸ”
  • tls_reqsan never|allow|try|demand|hard β€” how the server's Subject Alternative Name (SAN) gets checked in the server-supplied certificate. The values mean the same thing they mean in the ldap.conf(5) manual page. πŸ‘‘
  • tls_crlcheck none|peer|all β€” whether the CA's Certificate Revocation List (CRL) should be used to verify that the server certificates haven't been revoked. Values explained in ldap.conf(5), same deal. πŸ¦‹
  • tls_crlfile PATH β€” the path to the file containing a Certificate Revocation List, used to verify the server certificates. And again, the meaning of the values is described in the ldap.conf(5) manual page. 🌸

🌈 OTHER OPTIONS 🌈

  • pagesize NUMBER β€” set this to a number greater than 0 to request paged results from the LDAP server in accordance with RFC2696. The default (0) is to not request paged results.

This is a lifesaver for LDAP servers holding a LOT of entries (like, more than 500) that cap how many entries come back in one request. For OpenLDAP servers you may need to set sizelimit size.prtotal=unlimited so more entries can be returned across multiple pages. ✨

  • nss_initgroups_ignoreusers user1,user2,... β€” stops group membership lookups through LDAP for the users you list. Super useful when the LDAP server is just… not available. 😭 This option may be specified multiple times.

Alternatively you can pass the value ALLLOCAL, and with that, nslcd builds a full list of non-LDAP users on startup. 🫢

  • nss_min_uid UID β€” LDAP users with a numeric user id lower than the value you give here get ignored. Also, requests for users with a lower user id get ignored. 🚫
  • nss_uid_offset NUMBER β€” an offset that gets added to all LDAP numeric user ids. Handy for dodging user id collisions with local users, or for compatibility reasons when you're using objectSid attributes.

The value from the nss_min_uid option is evaluated after applying the offset. Important order of operations bestie. πŸ’…

  • nss_gid_offset NUMBER β€” an offset added to all LDAP numeric group ids. Same deal as above: avoids group id collisions with local groups, or helps for compatibility reasons when using objectSid attributes. πŸŽ€
  • nss_nested_groups yes|no β€” if this is set, the member attribute of a group may point to another group. Members of nested groups also come back in the higher level group, and parent groups get returned when finding groups for a specific user. The default is to not do extra searches for nested groups. 🌸
  • nss_getgrent_skipmembers yes|no β€” if this is set, the group member list is not retrieved when looking up groups. Lookups for finding which groups a user belongs to still work, so the user will likely still get the correct groups assigned on login.

It can speed things up on systems with very large groups. But the downside is it returns inconsistent information about group membership, which may confuse some applications. > This option is not recommended for most configurations. 😬

  • nss_disable_enumeration yes|no β€” if this is set, functions that cause all user/group entries to be loaded (getpwent(), getgrent(), setspent()) from the directory will not succeed in doing so. Applications that depend on being able to sequentially read all users and/or groups may fail to operate correctly.

This can dramatically reduce LDAP server load when there are a great number of users and/or groups. It's typically used where user/program access to enumerate the entire directory is undesirable, and changing the behavior of the user/program isn't possible. > This option is not recommended for most configurations. πŸ’€

  • validnames REGEX β€” use this to specify how user and group names are verified within the system. The pattern is used to check all user and group names that are requested and returned from LDAP.

The regular expression should be specified as a POSIX extended regular expression. The expression itself needs to be separated by slash (/) characters, and the i flag may be appended at the end to indicate the match should be case-insensitive. The default value is /^[a-z0-9._@$()]([a-z0-9._@$() \\~-]*[a-z0-9._@$()~-])?$/i ✨

  • ignorecase yes|no β€” whether or not to perform searches for group, netgroup, passwd, protocols, rpc, services and shadow maps using case-insensitive matching. ⚠️ Setting this to yes could open up the system to authorisation bypass vulnerabilities and introduce nscd cache poisoning vulnerabilities which allow denial of service. The default is to perform case-sensitive filtering of LDAP search results for the maps listed above. So like… be careful bestie. 🚨
  • pam_authc_ppolicy yes|no β€” whether password policy controls are requested and handled from the LDAP server when performing user authentication. By default the controls are requested and handled if available. πŸ‘‘
  • pam_authc_search FILTER β€” by default nslcd performs an LDAP search with the user's credentials after BIND (authentication) to make sure the BIND operation actually succeeded. The default search is a simple check to see if the user's DN exists.

You can specify a search filter that gets used instead. The same substitutions as with the pam_authz_search option are performed, and the search should at least return one entry.

The value BASE may be used to force the default search for the user DN.

The value NONE may be used to indicate that no search should be performed after BIND. > Note that some LDAP servers do not always return a correct error code as a result of a failed BIND operation (e.g. when an empty password is supplied). 😭

  • pam_authz_search FILTER β€” lets you flexibly fine tune the authorisation check that should be performed. The search filter you specify is executed, and if any entries match, access is granted β€” otherwise access is denied. πŸ”₯

The search filter can contain these variable references: $username, $service, $ruser, $rhost, $tty, $hostname, $fqdn, $domain, $dn, and $uid. These references are substituted in the search filter using the same syntax as described in the section on attribute mapping expressions below.

For example, to check that the user has a proper authorizedService value if the attribute is present (this almost emulates the pam_check_service_attr option in PADL's pam_ldap):

(&(objectClass=posixAccount)(uid=$username)(|(authorizedService=$service)(!(authorizedService=*))))

The pam_check_host_attr option can be emulated with:

(&(objectClass=posixAccount)(uid=$username)(|(host=$hostname)(host=$fqdn)(host=\*)))

This option may be specified multiple times, and all specified searches should at least return one entry for access to be granted. πŸ’œ

  • pam_password_prohibit_message "MESSAGE" β€” if this is set, password modification using pam_ldap will be denied and the message you specify gets presented to the user instead. Perfect for pointing your users at some other way of changing their password. πŸŽ€
  • reconnect_invalidate DB,DB,... β€” if set, nslcd will try to flush the specified external caches on start-up and whenever a connection to the LDAP server is re-established after an error. 🧹

DB can refer to one of the nsswitch maps, in which case nscd is contacted to flush its cache for the specified database. If DB is nfsidmap, nfsidmap is contacted to clear its cache.

Using this option ensures external caches get cleared of incorrect information (typically the absence of users) that may be hanging around because the LDAP server was unavailable. πŸ™ˆ

  • cache CACHE TIME [TIME] β€” configures the time entries are kept in the specified internal cache. ⏰

The first TIME value specifies how long to keep found entries in the cache. The second TIME value specifies how long to remember that a particular entry was not found. If the second parameter is absent, it's assumed to be the same as the first.

Time values are written as a number followed by an s for seconds, m for minutes, h for hours or d for days. Use 0 or off to disable the cache. ✨

Currently, the only cache that's supported is the dn2uid cache β€” it's the one that remembers DN-to-username lookups, which is exactly what gets used when the member attribute comes into play. Default time value for this cache? 15m. slay. ⏱️✨


πŸ—ΊοΈ SUPPORTED MAPS πŸ’–

okay so these are the maps that are supported, bestie. up in the options we just went through, they get referred to as MAP. here's the whole roster:

  • alias[es] β€” mail aliases. ⚠️ heads up though: most mail servers do not use the NSS interface when they want mail aliases β€” they just go read /etc/aliases themselves. not their problem, ig.
  • ether[s] β€” ethernet numbers, aka mac addresses. πŸ¦‹
  • group β€” posix groups. πŸ‘‘
  • host[s] β€” host names. 🌸
  • netgroup β€” host and user groups, used for access control. πŸ”
  • network[s] β€” network numbers. 🌈
  • passwd β€” posix users. πŸ’œ
  • protocol[s] β€” protocol definitions, same vibe as what's in /etc/protocols. 🧚
  • rpc β€” remote procedure call names and numbers. ✨
  • service[s] β€” network service names and numbers. πŸŽ€
  • shadow β€” shadow user password information. 🀫

✨ ATTRIBUTE MAPPING EXPRESSIONS ✨

so for some attributes you can use a mapping expression to build the resulting value. currently this is only possible for attributes that don't need to be used in search filters β€” no cap. the expressions are a subset of the double quoted string expressions from the Bourne (POSIX) shell. but instead of variable substitution, what happens is attribute lookups on the current entry, and then the attribute value gets substituted in. here's everything that's supported:

  • "${attr}" (or "$attr" for short) β€” will substitute the value of the attribute. πŸ’…
  • "${attr:-word}" β€” (use default) will substitute the value of the attribute, or, if the attribute is not set or is empty, substitute word instead.
  • "${attr:+word}" β€” (use alternative) will substitute word if the attribute is set, otherwise it substitutes the empty string.
  • "${attr:offset:length}" β€” will substitute length characters (actually bytes, fr) starting from position offset (and offset is counted starting at zero). the substituted string gets truncated if it's too long; in particular it can be of length zero (if length is zero, or if offset falls out of the original string). 😭
  • "${attr#word}" β€” remove the shortest possible match of word from the left of the attribute value.
  • "${attr##word}" β€” remove the longest possible match of word from the left of the attribute value (pynslcd only).
  • "${attr%word}" β€” remove the shortest possible match of word from the right of the attribute value (pynslcd only).
  • "${attr%%word}" β€” remove the longest possible match of word from the right of the attribute value (pynslcd only).
lowkey important: only the # matching expression is supported in nslcd, and only with the ? wildcard symbol. the pynslcd implementation supports full matching. πŸ’€

Quote ("), dollar ($) and backslash (\) characters should be escaped with a backslash (\). 🫢

The expressions get inspected so the appropriate attributes can be automatically fetched from LDAP. and now some examples to demonstrate how these expressions may be used in attribute mapping:

map shadow shadowFlag "${shadowFlag:-0}"

use the shadowFlag attribute, using the value 0 as default.

map passd homeDirectory "${homeDirectory:-/home/$uid}"

use the uid attribute to build a homeDirectory value if that attribute is missing.

map shadow shadowExpire "${isDisabled:+100}"

if the isDisabled attribute is set, return 100, otherwise leave the value empty.

map shadow userPassword "${userPassword#{crypt\}}"

strip the {crypt} prefix from the userPassword attribute, returning the raw hash value. πŸ’…


πŸ“‚ FILES πŸ“‚

  • /etc/nslcd.conf β€” the main configuration file. this is the one. 🌟
  • /etc/nsswitch.conf β€” Name Service Switch configuration file.

πŸ‘€ SEE ALSO πŸ‘€

nslcd(8), nsswitch.conf(5)


πŸŽ€ AUTHOR πŸŽ€

This manual was written by Arthur de Jong <arthur@arthurdejong.org> and is based on the nss_ldap(5) manual developed by PADL Software Pty Ltd. iconic honestly 🫢


and that's a wrap bestie!! πŸŽ‰ this was Version 0.9.13, dated Feb 2025, and the page is nslcd.conf(5). go configure ur LDAP, u got this. slay βœ¨πŸ’–πŸŽ€πŸ¦‹πŸŒΈπŸ’