SLAPD.CONF(5)

๐Ÿ’– SLAPD.CONF โ€” File Formats Manual ๐Ÿ’–

okay bestie, deep breath, because we are entering the File Formats Manual (that's the (5) in SLAPD.CONF(5), mwah) and this page is a whole journey. It's giving phonebook-sized. But don't panic, I've got you, we're doing this together. ๐Ÿซถ


โœจ NAME โœจ

slapd.conf โ€” the configuration file for slapd, the stand-alone LDAP daemon. She's the blueprint. The origin story. The config queen. ๐Ÿ‘‘


๐Ÿฆ‹ SYNOPSIS ๐Ÿฆ‹

/etc/openldap/slapd.conf

๐ŸŒธ DESCRIPTION ๐ŸŒธ

So the file /etc/openldap/slapd.conf is where all the configuration information for the slapd(8) daemon lives. And not just for the daemon bestie โ€” the SLAPD tools read it too: slapacl(8), slapadd(8), slapauth(8), slapcat(8), slapdn(8), slapindex(8), slapmodify(8), and slaptest(8). Like, the whole friend group shares this one file. iconic.

The structure is: a bunch of global configuration options that apply to slapd as a whole (all backends included, no one is exempt), and then zero or more database backend definitions that hold the info specific to one backend instance. Config options are case-insensitive, but their values might be case-sensitive on a case-by-case basis. So, like โ€” Option and OPTION are the same girl, but "Value" and "value" are not necessarily the same girl. ๐Ÿ’€

Here's the general format, verbatim:

# comment - these options apply to every database
<global configuration options>
# first database definition & configuration options
database <backend 1 type>
<configuration options specific to backend 1>
# subsequent database definitions & configuration options
...

You can include as many backend-specific sections as your heart desires. ๐Ÿ’• Global options can also be overridden inside a backend โ€” and if an option shows up more than once, the last appearance in the slapd.conf file is the one that wins. Last one standing, periodt.

If a line begins with white space, it counts as a continuation of the previous line. And no physical line should be over 2000 bytes long. (Yeah, 2000. Not 200, not 2048. 2000. Write it down. ๐Ÿ“)

Blank lines and comment lines that start with a # character are ignored. โš ๏ธ Note: continuation lines get unwrapped before comment processing happens โ€” so don't try anything cute with a # mid-continuation.

Arguments on configuration lines are separated by white space. If an argument itself contains white space, wrap it in double quotes. And if an argument contains a double quote (") or a backslash character (\), that character has to be preceded by a backslash. Escape your escapees, bestie. ๐Ÿ”

All the specific config options are discussed below in the Global Configuration Options, General Backend Options, and General Database Options sections. Backend-specific options get their own slapd-<backend>(5) manual pages. And for even more details, go read the "OpenLDAP Administrator's Guide". โœจ


๐Ÿ› ๏ธ GLOBAL CONFIGURATION OPTIONS ๐Ÿ› ๏ธ

Everything in this section applies to all backends, unless it's specifically overridden inside a backend definition. Arguments that should be replaced by actual text are shown in brackets <>. (That's your "fill in the blank", babe.)


๐Ÿ”‘ access to <what> [ by <who> <access> <control> ]+

Grant access (specified by <access>) to a set of entries and/or attributes (specified by <what>) by one or more requestors (specified by <who>).

If no access controls are present at all, the default policy lets anyone and everyone read anything, but restricts updates to rootdn. (Like, for real: "access to * by * read".)

โš ๏ธ Heads up: the rootdn can always read and write EVERYTHING! No ACL is stopping her. She's the main character. ๐Ÿ‘‘

See slapd.access(5) and the "OpenLDAP's Administrator's Guide" for the details.


โœ… allow <features>

Specify a set of features (separated by white space) to allow. Default is none โ€” you get nothing for free, sorry babe.

  • bind_v2 โ€” allows acceptance of LDAPv2 bind requests. Note that slapd(8) does not truly implement LDAPv2 (RFC 1777), now Historic (RFC 3494).
  • bind_anon_cred โ€” allows anonymous bind when credentials are not empty (e.g. when DN is empty).
  • bind_anon_dn โ€” allows unauthenticated (anonymous) bind when DN is not empty.
  • update_anon โ€” allows unauthenticated (anonymous) update operations to be processed (subject to access controls and other administrative limits).
  • proxy_authz_anon โ€” allows unauthenticated (anonymous) proxy authorization control to be processed (subject to access controls, authorization and other administrative limits).

๐Ÿ“„ argsfile <filename>

The (absolute) name of a file that will hold the slapd server's command line โ€” that's the program name and the options. Yes, absolute. Not "kinda absolute". Absolute. ๐ŸŽฏ


๐Ÿท๏ธ attributeoptions [option-name]...

Define tagging attribute options, or option tag/range prefixes. The rules: options must not end with -, and prefixes must end with -.

The lang- prefix is predefined. โš ๏ธ But if you use the attributeoptions directive, lang- will no longer be defined โ€” you have to specify it explicitly if you want it defined. She doesn't come along for the ride automatically anymore.

An attribute description with a tagging option is a subtype of that attribute description without the option. Other than that, options defined this way have no special semantics.

Prefixes defined this way work just like the lang- options: they define a prefix for tagging options that start with that prefix. So if you define the prefix x-foo-, you can use the option x-foo-bar. โœจ

Furthermore, in a search or compare, a prefix or range name (with a trailing -) matches all options starting with that name, as well as the option with the range name sans the trailing -. That is, x-foo-bar- matches x-foo-bar and x-foo-bar-baz. ๐Ÿ’…

RFC 4520 reserves options beginning with x- for private experiments. Other options should be registered with IANA โ€” see RFC 4520 section 3.5. OpenLDAP also has the binary option built in, but heads up: that's a transfer option, not a tagging option. Different category, bestie.


๐Ÿงฌ attributetype ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE] [SUP <oid>] [EQUALITY <oid>] [ORDERING <oid>] [SUBSTR <oid>] [SYNTAX <oidlen>] [SINGLE-VALUE] [COLLECTIVE] [NO-USER-MODIFICATION] [USAGE <attributeUsage>] )

Specify an attribute type using the LDAPv3 syntax defined in RFC 4512.

The slapd parser extends the RFC 4512 definition by allowing string forms as well as numeric OIDs to be used for the attribute OID and the attribute syntax OID. (See the objectidentifier description.) So yes bestie, you can be numeric or name-y. ๐ŸŒˆ


๐Ÿ” authid-rewrite<cmd> <args>

Used by the authentication framework to convert simple user names into an LDAP DN used for authorization purposes. Its purpose is analogous to that of authz-regexp (see below).

The prefix authid- is followed by a set of rules analogous to those described in slapo-rwm(5) for data rewriting โ€” just replace the rwm- prefix with authid-.

โš ๏ธ authid-rewrite<cmd> and authz-regexp rules should not be intermixed. Pick a lane, queen. ๐Ÿšซ

๐ŸŽญ authz-policy <policy>

Used to specify which rules to use for Proxy Authorization. So what is proxy authorization? It lets a client authenticate to the server using one user's credentials, but then specify a different identity to use for authorization and access control purposes. Essentially, it allows user A to login as user B, using user A's password. ๐Ÿ˜ณ iconic and also slightly terrifying.

The flags:

  • none โ€” disables proxy authorization. This is the default setting.
  • from โ€” will use rules in the authzFrom attribute of the authorization DN.
  • to โ€” will use rules in the authzTo attribute of the authentication DN.
  • any โ€” an alias for the deprecated value of both, will allow any of the above, whatever succeeds first (checked in to, from sequence).
  • all โ€” requires both authorizations to succeed.

The rules are mechanisms to specify which identities are allowed to perform proxy authorization. The authzFrom attribute in an entry specifies which other users are allowed to proxy login to this entry. The authzTo attribute in an entry specifies which other users this user can authorize as.

๐Ÿšจ Use of authzTo rules can be easily abused if users are allowed to write arbitrary values to this attribute. In general the authzTo attribute must be protected with ACLs such that only privileged users can modify it. This is the "don't let just anybody touch this" warning. fr fr.

The value of authzFrom and authzTo describes an identity or a set of identities; it can take five forms:

ldap:///<base>??[<scope>]?<filter>
dn[.<dnstyle>]:<pattern>
u[.<mech>[/<realm>]]:<pattern>
group[/objectClass[/attributeType]]:<pattern>
<pattern>

<dnstyle>:={exact|onelevel|children|subtree|regex}

Let's break those down, one by one. ๐Ÿงš

1. The first form is a valid LDAP URI where the <host>:<port>, the <attrs> and the <extensions> portions must be absent, so that the search occurs locally on either authzFrom or authzTo.

2. The second form is a DN. The optional dnstyle modifiers exact, onelevel, children, and subtree provide exact, onelevel, children and subtree matches, which cause <pattern> to be normalized according to the DN normalization rules. The special dnstyle modifier regex causes the <pattern> to be treated as a POSIX ("extended") regular expression, as discussed in regex(7) and/or re_format(7). A pattern of * means any non-anonymous DN.

3. The third form is a SASL id. The optional fields <mech> and <realm> allow specification of a SASL mechanism, and eventually a SASL realm, for those mechanisms that support one. โš ๏ธ The need to allow the specification of a mechanism is still debated, and users are strongly discouraged to rely on this possibility. Don't do it, babe.

4. The fourth form is a group specification. It consists of the keyword group, optionally followed by the specification of the group objectClass and attributeType. The objectClass defaults to groupOfNames. The attributeType defaults to member. The group with DN <pattern> is searched with base scope, filtered on the specified objectClass. The values of the resulting attributeType are searched for the asserted DN.

5. The fifth form is provided for backwards compatibility. If no identity type is provided, i.e. only <pattern> is present, an exact DN is assumed; as a consequence, <pattern> is subjected to DN normalization.

๐Ÿ’ก Since the interpretation of authzFrom and authzTo can impact security, users are strongly encouraged to explicitly set the type of identity specification that is being used. A subset of these rules can be used as third arg in the authz-regexp statement (see below); significantly, the URI, provided it results in exactly one entry, and the dn.exact:<dn> forms.

๐ŸŒˆ okay that's the end of part 1, don't go anywhere โ€” there's so much more of this page and I'm not done yapping, stay with me bestie ๐Ÿ’–

  • authz-regexp <match> <replace> โ€” bestie this is the authentication framework's whole translation service ๐Ÿ’ซ it takes simple user names โ€” like the ones the SASL subsystem hands over, or the ones yanked out of certificates when it's cert-based SASL EXTERNAL, or the ones that show up inside the RFC 4370 "proxied authorization" control โ€” and turns them into an LDAP DN that gets used for authorization. And heads up: the DN it spits out does not have to point at an actual existing entry to count as valid. No cap.

So here's the flow: when an authorization request arrives from the SASL subsystem, the SASL USERNAME, REALM, and MECHANISM get grabbed (when they're available) and combined into a name shaped like this:

UID=<username>[[,CN=<realm>],CN=<mechanism>],CN=auth

That name then gets compared against the match POSIX ("extended") regular expression, and if the match hits, the name gets swapped for the replace string. If the match regex has wildcard strings wrapped in parentheses, like

UID=([^,]*),CN=.*

then whatever chunk of the name matched that wildcard gets stashed in the numbered placeholder $1. Got more parenthesised wildcards? Those matching strings land in $2, $3, etc., all the way up to $9. Then you get to use those placeholders in the replace string, like:

UID=$1,OU=Accounts,DC=example,DC=com

The replaced name can be either a DN (i.e. a string prefixed by dn:) or an LDAP URI. If it's a URI, the server takes that URI and searches its own database(s) with it, and if the search comes back with exactly one entry, the name gets replaced by that entry's DN. The LDAP URI has to have no hostport, attrs, or extensions components, but the filter is mandatory, like:

ldap:///OU=Accounts,DC=example,DC=com??one?(UID=$1)

The protocol portion of that URI has to be strictly ldap โ€” no substitutions, bestie. Also important: this search is subject to access controls. Specifically, the authentication identity needs to hold "auth" access in the subject. ๐Ÿ‘‘

You can drop multiple authz-regexp options into the config file to get multiple matching-and-replacement patterns going. They get checked in the order they appear in the file, and the first successful match wins, periodt.

  • concurrency <integer> โ€” sets your desired level of concurrency ๐Ÿงš it's handed to the underlying thread system as a hint. The default is to not give any hint at all. This setting only actually means something on some platforms โ€” the ones where there isn't a one-to-one correspondence between user threads and kernel threads. So like, platform-dependent vibes.
  • conn_max_pending <integer> โ€” the max number of pending requests allowed for an anonymous session. If requests get submitted faster than the server can chew through them, they queue up to this limit, and if the limit gets exceeded, the session is just closed. The default is 100.
  • conn_max_pending_auth <integer> โ€” same deal but for an authenticated session ๐Ÿซถ the max number of pending requests. The default is 1000.
  • defaultsearchbase <dn> โ€” gives you a default search base to use when the client submits a non-base search request with an empty base DN. Note that base-scoped search requests with an empty base DN are not affected by this. Different situation.
  • disallow <features> โ€” lists a set of features to disallow, separated by white space (default is none). Here's the menu:
    • bind_anon โ€” disables acceptance of anonymous bind requests. Just know this setting does not prohibit anonymous directory access (peep "require authc" for that one).
    • bind_simple โ€” disables simple (bind) authentication.
    • tls_2_anon โ€” disables forcing the session to anonymous status (see also tls_authc) upon receipt of a StartTLS operation.
    • tls_authc โ€” disallows the StartTLS operation if authenticated (see also tls_2_anon).
    • proxy_authz_non_critical โ€” disables acceptance of the proxied authorization control (RFC4370) with criticality set to FALSE.
    • dontusecopy_non_critical โ€” disables acceptance of the dontUseCopy control (a work in progress, iykyk) with criticality set to FALSE.
  • ditcontentrule ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE] [AUX <oids>] [MUST <oids>] [MAY <oids>] [NOT <oids>] ) โ€” defines a DIT Content Rule using the LDAPv3 syntax from RFC 4512 โœจ The slapd parser extends that RFC 4512 definition by letting you use string forms as well as numeric OIDs for the attribute OID and the attribute syntax OID. (Go look at the objectidentifier description for the details.)
  • gentlehup { on | off } โ€” okay so when this is on, a SIGHUP signal only triggers a 'gentle' shutdown-attempt ๐Ÿ’… Slapd stops listening for new connections, but it does not close the connections to current clients. That said, future write operations return unwilling-to-perform. Slapd terminates when all clients have closed their connections (if they ever do), or โ€” same as before โ€” if it catches a SIGTERM signal. This is genuinely useful if you wanna kill the server and spin up a fresh slapd with a different database without wrecking the clients that are active right now. The default is off. You may wanna pair this with the idletimeout option while you're at it.
  • idletimeout <integer> โ€” how many seconds to wait before forcibly closing an idle client connection. A setting of 0 disables the feature entirely. The default is 0. You might also want to set the writetimeout option btw.
  • include <filename> โ€” read extra configuration info from the given file before moving on to the next line of the current file. Snack break, then back to it. ๐Ÿ“–
  • index_hash64 { on | off } โ€” use a 64 bit hash for indexing; otherwise it's 32 bit. The default is now 64 bit. These hashes power equality and substring indexing. The 64 bit version dodges index collisions once the number of indexed values climbs past ~64 million. (And note that substring indexing generates multiple index values per actual attribute value, so yeah, that adds up.) โš ๏ธ Indices built with 32 bit hashes are incompatible with the 64 bit version, and vice versa. Any existing databases have to be fully reindexed when you flip this setting. And since 64 bit is now the default, this option is deprecated and will eventually be removed โ€” so don't get attached.
  • index_intlen <integer> โ€” the key length for ordered integer indices. The most significant bytes of the binary integer get used for the index keys. The default value is 4, which gives you exact indexing for 31 bit values. A floating point representation is used to index values that are too large.
  • index_substr_if_maxlen <integer> โ€” the maximum length for subinitial and subfinal indices. Only this many characters of an attribute value get processed by the indexing functions; anything extra is just ignored. The default is 4.
  • index_substr_if_minlen <integer> โ€” the minimum length for subinitial and subfinal indices. An attribute value needs at least this many characters before the indexing functions will even touch it. The default is 2.
  • index_substr_any_len <integer> โ€” the length used for subany indices. An attribute value needs at least this many characters to get processed, and values longer than this length get processed in segments of this length. The default is 4. Also, the subany index gets used in subinitial and subfinal index lookups whenever the filter string is longer than the index_substr_if_maxlen value. Multi-tasking icon.
  • index_substr_any_step <integer> โ€” the steps used in subany index lookups. This value sets the offset for the segments of a filter string that get processed for a subany index lookup. The default is 2. For example, with the default values, a search using this filter "cn=*abcdefgh*" would generate index lookups for "abcd", "cdef", and "efgh". Look at her go ๐ŸŒˆ
Note: Indexing support depends on the particular backend in use. Also, changing these settings will generally require deleting any indices that depend on these parameters and recreating them with slapindex(8). So plan accordingly bestie, no shortcuts.
  • ldapsyntax ( <oid> [DESC <description>] [X-SUBST <substitute-syntax>] ) โ€” defines an LDAP syntax using the LDAPv3 syntax from RFC 4512 ๐Ÿฆ‹ The slapd parser extends that RFC 4512 definition by allowing string forms as well as numeric OIDs for the syntax OID. (Again, see the objectidentifier description.) The slapd parser also honors the X-SUBST extension (an OpenLDAP-specific one), which lets you use the ldapsyntax statement to define a not-yet-implemented syntax alongside another syntax โ€” the extension value substitute-syntax โ€” as its temporary stand-in. The substitute-syntax must be defined. This is what lets you define attribute types that use non-implemented syntaxes with the correct syntax OID. And heads up: unless X-SUBST is used, this configuration statement would just error out, because no handlers would be associated with the resulting syntax structure. ๐Ÿ’€
  • listener-threads <integer> โ€” the number of threads to use for the connection manager. The default is 1, and that's typically plenty for up to 16 CPU cores. The value should be set to a power of 2, okay?
  • localSSF <SSF> โ€” specifies the Security Strength Factor (SSF) given to local LDAP sessions, like the ones going to the ldapi:// listener. For the breakdown of SSF values, check out sasl-secprops's minssf option description. The default is 71.
  • logfile <filename> โ€” a file for recording slapd debug messages ๐Ÿ“ These messages are unrelated to the messages exposed by the loglevel configuration parameter, jsyk. This setting only affects the slapd daemon itself and has zero effect on the command line tools. By default these messages only go to stderr and aren't recorded anywhere else. If you specify a logfile, messages get copied to both stderr and the logfile. Best of both worlds.
  • logfile-format debug|syslog-utc|syslog-localtime|rfc3339-utc โ€” the prefix format for messages written to the logfile โœจ The debug format is the normal format used for slapd debug messages, with a timestamp in hexadecimal followed by a thread ID. The other options use syslog(3) style prefixes, with timestamps either in UTC or in the local timezone. The default is debug format.
  • logfile-only on | off โ€” bestie, flip this on and your debug tea โ˜• goes only to the configured logfile, not to stderr. That's it, that's the whole vibe. ๐Ÿ’…
  • logfile-rotate <max> <Mbytes> <hours> โ€” this one sets up auto-rotation for your configured logfile, and it takes three little values: <max> is the max number of old logfiles to keep around, <Mbytes> is the max size in megabytes a logfile can hit before it gets rotated, and <hours> is the max age in hours a logfile can reach before it gets rotated. The <max> number has to be in the range 1-99. Setting <Mbytes> or <hours> to zero disables the size check or the age check respectively. And listen โ€” at least one of <Mbytes> or <hours> has to be non-zero, no exceptions. By default there's no automatic rotation happening at all. ๐ŸŽ€
  • loglevel <integer> [...] โ€” okay so this sets the level at which debugging statements and operation statistics get syslogged (currently these go to the syslogd(8) LOG_LOCAL4 facility). Important thing: these are not "more verbosity = higher level" type deals, they're subsystems. Some messages with higher priority get logged no matter what your loglevel is, as soon as any logging is configured at all. Log levels are additive, and here's the full menu of available levels:
    • 1 (0x1 trace) โ€” trace function calls
    • 2 (0x2 packets) โ€” debug packet handling
    • 4 (0x4 args) โ€” heavy trace debugging (function args)
    • 8 (0x8 conns) โ€” connection management
    • 16 (0x10 BER) โ€” print out packets sent and received
    • 32 (0x20 filter) โ€” search filter processing
    • 64 (0x40 config) โ€” configuration file processing
    • 128 (0x80 ACL) โ€” access control list processing
    • 256 (0x100 stats) โ€” connections, LDAP operations, results (recommended)
    • 512 (0x200 stats2) โ€” stats2 log entries sent
    • 1024 (0x400 shell) โ€” print communication with shell backends
    • 2048 (0x800 parse) โ€” entry parsing
    • 16384 (0x4000 sync) โ€” LDAPSync replication
    • 32768 (0x8000 none) โ€” only messages that get logged whatever log level is set

You can drop the desired log level in as a single integer that combines the (ORed) desired levels โ€” decimal or hexadecimal both work โ€” or as a list of integers (which get ORed internally), or as a list of the names shown in those parentheses above. So these are all the SAME thing, fr fr:

loglevel 129
loglevel 0x81
loglevel 128 1
loglevel 0x80 0x1
loglevel acl trace

The keyword any is a shortcut to enable logging at all levels (equivalent to -1). And the keyword none, or its equivalent integer representation, causes those messages that get logged regardless of the configured loglevel to be logged. Real talk: if loglevel is set to 0, no logging occurs at all, so you need at least the none level to get those high-priority messages logged.

โš ๏ธ Heads up bestie: the packets, BER, and parse levels are only available as debug output on stderr, and are not sent to syslog. Don't come crying to me when they don't show up there. ๐Ÿ˜ญ

The loglevel defaults to stats. And you should usually keep that level in the mix when you're using other loglevels too, so your logs actually make sense to analyze later. ๐Ÿฆ‹

  • maxfilterdepth <integer> โ€” caps the maximum depth of nested filters in search requests. The default is 1000. โœจ
  • maxQtime <integer> โ€” sets the maximum time for operations to be queued before executing, in microseconds. Operations that blow past this time get rejected with zero further processing. The default is 0, which disables the check entirely. ๐Ÿ“
  • moduleload <filename> [<arguments>...] โ€” names a dynamically loadable module to load, plus any extra arguments if the module supports them. The filename can be an absolute path name or just a simple filename โ€” non-absolute names get searched for in the directories given by the modulepath option. And lowkey important: this option and the modulepath option are only usable if slapd was compiled with --enable-modules. ๐Ÿซถ
  • modulepath <pathspec> โ€” a list of directories to search for loadable modules. Typically the path is colon-separated, but ngl that depends on the operating system. The default is /usr/lib/openldap, which is where the standard OpenLDAP install drops its modules. ๐Ÿ‘‘
  • objectclass ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE] [SUP <oids>] [{ ABSTRACT | STRUCTURAL | AUXILIARY }] [MUST <oids>] [MAY <oids>] ) โ€” defines an objectclass using the LDAPv3 syntax from RFC 4512. The slapd parser is extra and extends the RFC 4512 definition by allowing string forms as well as numeric OIDs for the object class OID. (Peep the objectidentifier description below for that.) Object classes are "STRUCTURAL" by default. ๐Ÿ’…
  • objectidentifier <name> { <oid> | <name>[:<suffix>] } โ€” defines a string name that equals the given OID. You can use that string in place of the numeric OID in objectclass and attribute definitions. The name can also take a suffix of the form ":xx", in which case the value "oid.xx" gets used. โœจ
  • password-hash <hash> [<hash>...] โ€” configures one or more hashes to be used when generating user passwords stored in the userPassword attribute during processing of LDAP Password Modify Extended Operations (RFC 3062). The <hash> has to be one of {SSHA}, {SHA}, {SMD5}, {MD5}, {CRYPT}, and {CLEARTEXT}. The default is {SSHA}. Here's the tea on each:
    • {SHA} and {SSHA} use the SHA-1 algorithm (FIPS 160-1), the latter with a seed.
    • {MD5} and {SMD5} use the MD5 algorithm (RFC 1321), the latter with a seed.
    • {CRYPT} uses the crypt(3).
    • {CLEARTEXT} means the new password gets added to userPassword as clear text. ๐Ÿ™ˆ
Just so we're clear: this option does not alter the normal user applications handling of userPassword during LDAP Add, Modify, or other LDAP operations. K? ๐Ÿ’–
  • password-crypt-salt-format <format> โ€” sets the format of the salt passed to crypt(3) when generating {CRYPT} passwords (see password-hash) during processing of LDAP Password Modify Extended Operations (RFC 3062). This string needs to be in sprintf(3) format and may include one (and only one) %s conversion. That conversion gets substituted with a string of random characters from [A-Za-z0-9./]. For example, "%.2s" provides a two character salt, and "$1$%.8s" tells some versions of crypt(3) to use an MD5 algorithm and provides 8 random characters of salt. The default is "%s", which provides 31 characters of salt. ๐Ÿงš
  • pidfile <filename> โ€” the (absolute) name of a file that will hold the slapd server's process ID (see getpid(2)). โญ
  • pluginlog: <filename> โ€” the ( absolute ) name of a file that will contain log messages from SLAPI plugins. See slapd.plugin(5) for details. ๐ŸŒธ
  • referral <url> โ€” specifies the referral to pass back when slapd(8) can't find a local database to handle a request. If you specify it multiple times, each url gets provided. ๐Ÿฆ‹
  • require <conditions> โ€” a set of conditions (separated by white space) to require (default none). This directive can be set globally and/or per-database; databases inherit global conditions, so per-database specifications are additive. Here's the condition menu:
    • bind โ€” requires a bind operation prior to directory operations.
    • LDAPv3 โ€” requires the session to be using LDAP version 3.
    • authc โ€” requires authentication prior to directory operations.
    • SASL โ€” requires SASL authentication prior to directory operations.
    • strong โ€” requires strong authentication prior to directory operations. The strong keyword allows protected "simple" authentication as well as SASL authentication.
    • none โ€” may be used to require no conditions (useful to clear out globally set conditions within a particular database). It must occur first in the list of conditions. ๐Ÿ’€
  • reverse-lookup on | off โ€” enable/disable client name unverified reverse lookup (default is off if compiled with --enable-rlookups). ๐Ÿ”ฅ
  • rootDSE <file> โ€” names an LDIF(5) file containing user defined attributes for the root DSE. These attributes get returned in addition to the attributes normally produced by slapd. The root DSE is an entry with info about the server and its capabilities, in operational attributes. It has the empty DN, and you can read it with e.g.:
ldapsearch -x -b "" -s base "+"

See RFC 4512 section 5.1 for details. ๐Ÿ‘‘

  • sasl-auxprops <plugin> [...] โ€” which auxprop plugins to use for authentication lookups. The default is empty, which just uses slapd's internal support. Usually you don't need any other auxprop plugins, no cap. ๐Ÿ’œ
  • sasl-auxprops-dontusecopy <attr> [...] โ€” which attribute(s) should be subject to the don't use copy control. This is necessary for some SASL mechanisms such as OTP to work in a replicated environment. The attribute "cmusaslsecretOTP" is the default value. โœจ
  • sasl-auxprops-dontusecopy-ignore on | off โ€” used to disable replication of the attribute(s) defined by sasl-auxprops-dontusecopy and instead use a local value for the attribute. This lets the SASL mechanism keep working if the provider is offline. โš ๏ธ Warning though: this can cause replication inconsistency. Defaults to off. ๐Ÿ˜ญ
  • sasl-host <fqdn> โ€” used to specify the fully qualified domain name used for SASL processing. ๐ŸŽ€
  • sasl-realm <realm> โ€” specifies the SASL realm. Default is empty. ๐ŸŒˆ
  • sasl-cbinding none | tls-unique | tls-endpoint โ€” specifies the channel-binding type, see also LDAP_OPT_X_SASL_CBINDING. Default is none. ๐Ÿ’…
  • sasl-secprops <properties> โ€” this is where you tell Cyrus SASL what security vibes you require, bestie. So many little flags:
    • none โ€” on its own, with no other properties, clears the default flag properties "noanonymous,noplain". Just yeets them. ๐Ÿ’…
    • noplain โ€” disables mechanisms that are susceptible to simple passive attacks.
    • noactive โ€” disables mechanisms susceptible to active attacks.
    • nodict โ€” disables mechanisms susceptible to passive dictionary attacks.
    • noanonymous โ€” disables mechanisms that support anonymous login. no anon era ๐Ÿ”ฅ
    • forwardsec โ€” require forward secrecy between sessions.
    • passcred โ€” require mechanisms which pass client credentials (and allow mechanisms which can pass credentials to do so).
    • minssf=<factor> โ€” the minimum acceptable security strength factor, an integer approximating the effective key length used for encryption. 0 (zero) means no protection, 1 means integrity protection only, 128 allows RC4, Blowfish and other similar ciphers, and 256 will require modern ciphers. Default is 0.
    • maxssf=<factor> โ€” the maximum acceptable security strength factor, an integer (same idea as minssf up there โฌ†๏ธ). Default is INT_MAX.
    • maxbufsize=<size> โ€” the maximum security layer receive buffer size allowed. 0 disables security layers entirely. Default is 65536.
  • schemadn <dn> โ€” sets the distinguished name for the subschema subentry that controls the entries on this server. Default is "cn=Subschema" ๐ŸŽ€
  • security <factors> โ€” give it a set of security strength factors (separated by white space) that you wanna require. You can use this both globally and/or per-database, bestie, flexible king. The details:
    • ssf=<n> โ€” the overall security strength factor.
    • transport=<n> โ€” the transport security strength factor.
    • tls=<n> โ€” the TLS security strength factor.
    • sasl=<n> โ€” the SASL security strength factor.
    • update_ssf=<n> โ€” the overall security strength factor to require for directory updates.
    • update_transport=<n> โ€” the transport security strength factor to require for directory updates.
    • update_tls=<n> โ€” the TLS security strength factor to require for directory updates.
    • update_sasl=<n> โ€” the SASL security strength factor to require for directory updates.
    • simple_bind=<n> โ€” the security strength factor required for simple username/password authentication.

Heads up: the transport factor is a measure of security provided by the underlying transport, like ldapi:// (and eventually IPSEC). It's not normally used, so don't stress it. โœจ

  • serverID <integer> [<URL>] โ€” gives this server an integer ID from 0 to 4095. You can also write it as a hexadecimal ID by prefixing the value with "0x". Non-zero IDs are required when you're doing multi-provider replication, and each provider needs its own unique non-zero ID. That same requirement also applies to separate providers contributing to a glued set of databases, so no skipping it. ๐Ÿ‘‘

If you pass the <URL>, you can use this directive multiple times to hand over a complete list of participating servers and their IDs. Use the fully qualified hostname of each server in the URLs you supply. The IDs get used in the "replica id" field of all CSNs generated by the specified server. Default value is zero, which is only valid for single provider replication. Example:

serverID 1 ldap://ldap1.example.com
serverID 2 ldap://ldap2.example.com
  • sizelimit {<integer>|unlimited}
  • sizelimit size[.{soft|hard}]=<integer> [...] โ€” the maximum number of entries to return from a search operation. Default size limit is 500. Use unlimited for, well, no limits, no cap. ๐Ÿ’€ The second format lets you do a fine-grain setting of the size limits: if you don't specify any special qualifiers, both soft and hard limits get set. Extra args can be added on the same line. There are additional qualifiers too โ€” peep limits for an explanation of all the different flags.
  • sockbuf_max_incoming <integer> โ€” the maximum incoming LDAP PDU size for anonymous sessions. Default is 262143.
  • sockbuf_max_incoming_auth <integer> โ€” the maximum incoming LDAP PDU size for authenticated sessions. Default is 4194303.
  • sortvals <attr> [...] โ€” give it a list of multi-valued attributes whose values will always be maintained in sorted order. Do this and Modify, Compare, and filter evaluations on those attributes get to run more efficiently, slay. But watch out: the resulting sort order depends on the attributes' syntax and matching rules and might not correspond to lexical order or any other recognizable order. It's giving chaotic but functional. ๐Ÿฆ‹
  • tcp-buffer [listener=<URL>] [{read|write}=]<size> โ€” the size of the TCP buffer. A global value for both the read and write TCP buffers related to any listener is defined, unless the listener is explicitly specified, or either the read or write qualifiers are used. See tcp(7) for the deets. Also, some OS-es implement automatic TCP buffer tuning, so iykyk. ๐ŸŒธ
  • threads <integer> โ€” the maximum size of the primary thread pool. Default is 16; the minimum value is 2.
  • threadqueues <integer> โ€” the number of work queues to use for the primary thread pool. Default is 1, and that's typically adequate for up to 8 CPU cores. The value should not exceed the number of CPUs in the system. โญ
  • timelimit {<integer>|unlimited}
  • timelimit time[.{soft|hard}]=<integer> [...] โ€” the maximum number of seconds (in real time) that slapd will spend answering a search request. Default time limit is 3600. Use unlimited for no limits, obviously. ๐Ÿซถ The second format allows a fine-grain setting of the time limits, and extra args can be added on the same line. See limits for an explanation of the different flags.
  • tool-threads <integer> โ€” the maximum number of threads to use in tool mode. This should not be greater than the number of CPUs in the system. Default is 1.
  • writetimeout <integer> โ€” the number of seconds to wait before forcibly closing a connection with an outstanding write. This lets you recover from various network hang conditions, iconic honestly. A writetimeout of 0 disables this feature. The default is 0.

๐Ÿ’– TLS OPTIONS ๐Ÿ’–

okay so if slapd was built with TLS support (Transport Layer Security, the thing that keeps your traffic from being a whole public conversation ๐Ÿ‘€), there are extra options you get to play with. bestie, the vibes are secure โœจ

  • TLSCipherSuite <cipher-suite-spec> โ€” lets you pick which ciphers get accepted and what order they come in. <cipher-suite-spec> should be a cipher spec for whichever TLS library you're running: OpenSSL or GnuTLS. This directive is not supported when using MbedTLS. ๐Ÿ’… Example:
OpenSSL:
       TLSCipherSuite HIGH:MEDIUM:+SSLv2

GnuTLS:
       TLSCiphersuite SECURE256:!AES-128-CBC

want to see what a given spec actually selects in OpenSSL? run:

openssl ciphers -v <cipher-suite-spec>

with GnuTLS, the available specs live in the manual page of gnutls-cli(1) (check the description of the option --priority). ๐ŸŒธ in older versions of GnuTLS, where gnutls-cli doesn't support --priority, you can get the โ€” more limited โ€” list of ciphers like this:

gnutls-cli -l
  • TLSCACertificateFile <filename> โ€” this one points at the file holding certificates for all the Certificate Authorities slapd is willing to recognize. the certificate for the CA that signed the server certificate must(GnuTLS)/may(OpenSSL) be included among these certificates ๐Ÿซถ. if the signing CA wasn't a top-level (root) CA, you should have certificates for the entire sequence of CA's from the signing CA all the way up to the top-level CA. multiple certificates? just append them to the file โ€” the order is not significant, no cap. โœจ
  • TLSCACertificatePath <path> โ€” the path of directories that hold Certificate Authority certificates in separate individual files. usually you use only one of this or TLSCACertificateFile, but if you specify both, both locations will be used. you can specify multiple directories, separated by a semi-colon. ๐ŸŒˆ
  • TLSCertificateFile <filename> โ€” the file that contains the slapd server certificate, periodt. when using OpenSSL, that file may also contain any number of intermediate certificates after the server certificate. ๐ŸŽ€
  • TLSCertificateKeyFile <filename> โ€” the file with the slapd server private key that matches the certificate stored in the TLSCertificateFile file. currently, the private key must not be protected with a password, so it is of critical importance that it is protected carefully. ๐Ÿ”ฅ like, guard that thing with your life, i'm so serious.
โš ๏ธ no password on the private key means file permissions are literally your only defense. treat it like your diary.
  • TLSDHParamFile <filename> โ€” specifies the file containing parameters for Diffie-Hellman ephemeral key exchange. this is required in order to use a DSA certificate on the server, or an RSA certificate missing the "key encipherment" key usage. heads up though: setting this option may also enable Anonymous Diffie-Hellman key exchanges in certain non-default cipher suites. anonymous key exchanges should generally be avoided since they provide no actual client or server authentication and provide no protection against man-in-the-middle attacks ๐Ÿ˜ญ. you should append "!ADH" to your cipher suites to ensure these suites are not used. this directive is not supported when using MbedTLS.
  • TLSECName <name> โ€” specify the name of the curve(s) to use for Elliptic curve Diffie-Hellman ephemeral key exchange. this option is only used for OpenSSL. it is not used with GnuTLS โ€” the curves may be chosen in the GnuTLS ciphersuite specification. ๐Ÿฆ‹
  • TLSProtocolMin <major>[.<minor>] โ€” sets the minimum SSL/TLS protocol version that will be negotiated. if the server doesn't support at least that version, the SSL handshake will fail, sorry bestie ๐Ÿ’€. want to require TLS 1.x or higher? set this option to 3.(x+1), like:
TLSProtocolMin 3.2

that would require TLS 1.1. specifying a minimum that is higher than what the OpenLDAP implementation supports will result in it requiring the highest level that it does support. this directive is ignored with GnuTLS.

  • TLSRandFile <filename> โ€” the file to obtain random bits from when /dev/[u]random is not available. generally set to the name of the EGD/PRNGD socket. the environment variable RANDFILE can also be used to specify the filename. this directive is ignored with GnuTLS. ๐ŸŽฒ
  • TLSVerifyClient <level> โ€” specifies what checks to perform on client certificates in an incoming TLS session, if any. <level> can be one of these keywords:
    • never โ€” this is the default. slapd will not ask the client for a certificate.
    • allow โ€” the client certificate is requested. if no certificate is provided, the session proceeds normally. if a bad certificate is provided, it will be ignored and the session proceeds normally. ๐Ÿซถ
    • try โ€” the client certificate is requested. if no certificate is provided, the session proceeds normally. if a bad certificate is provided, the session is immediately terminated.
    • demand | hard | true โ€” these keywords are all equivalent, for compatibility reasons. the client certificate is requested. if no certificate is provided, or a bad certificate is provided, the session is immediately terminated. not me being strict ๐Ÿ’…
note that a valid client certificate is required in order to use the SASL EXTERNAL authentication mechanism with a TLS session. as such, a non-default TLSVerifyClient setting must be chosen to enable SASL EXTERNAL authentication.
  • TLSCRLCheck <level> โ€” specifies if the Certificate Revocation List (CRL) of the CA should be used to verify that client certificates have not been revoked. this requires the TLSCACertificatePath parameter to be set. this directive is ignored with GnuTLS. <level> can be one of these keywords:
    • none โ€” no CRL checks are performed
    • peer โ€” check the CRL of the peer certificate
    • all โ€” check the CRL for a whole certificate chain
  • TLSCRLFile <filename> โ€” specifies a file containing a Certificate Revocation List to be used for verifying that certificates have not been revoked. this directive is only valid when using GnuTLS. ๐ŸŽ€

๐ŸŒŸ GENERAL BACKEND OPTIONS ๐ŸŒŸ

okay so options in this section only apply to the configuration file section of all instances of the specified backend. all backends may support this class of options, but currently only back-mdb does. iykyk. โœจ

  • backend <databasetype> โ€” mark the beginning of a backend definition. <databasetype> should be one of asyncmeta, config, dnssrv, ldap, ldif, mdb, meta, monitor, null, passwd, relay, sock, or wt. at present, only back-mdb implements any options of this type, so this setting is not needed for any other backends. ๐Ÿซถ

๐Ÿ’… GENERAL DATABASE OPTIONS ๐Ÿ’…

options in this section only apply to the configuration file section for the database in which they are defined. they're supported by every type of backend. note that the database and at least one suffix option are mandatory for each database โ€” no skipping, bestie. ๐Ÿ‘‘

  • database <databasetype> โ€” mark the beginning of a new database instance definition. <databasetype> should be one of asyncmeta, config, dnssrv, ldap, ldif, mdb, meta, monitor, null, passwd, relay, sock, or wt, depending on which backend will serve the database. ๐Ÿฆ‹

LDAP operations, even subtree searches, normally access only one database. that can be changed by gluing databases together with the subordinate keyword. access controls and some overlays can also involve multiple databases.

  • add_content_acl on | off โ€” controls whether Add operations will perform ACL checks on the content of the entry being added. this check is off by default. see the slapd.access(5) manual page for more details on ACL requirements for Add operations. ๐Ÿ”
  • extra_attrs <attrlist> โ€” lists what attributes need to be added to search requests. local storage backends return the entire entry to the frontend. the frontend takes care of only returning the requested attributes that are allowed by ACLs. however, features like access checking and so may need specific attributes that are not automatically returned by remote storage backends, like proxy backends and so on. <attrlist> is a list of attributes that are needed for internal purposes and thus always need to be collected, even when not explicitly requested by clients. ๐ŸŽ€
  • hidden on | off โ€” controls whether the database will be used to answer queries. a database that is hidden will never be selected to answer any queries, and any suffix configured on the database will be ignored in checks for conflicts with other databases. by default, hidden is off. ๐Ÿ™ˆ
  • lastmod on | off โ€” controls whether slapd will automatically maintain the modifiersName, modifyTimestamp, creatorsName, and createTimestamp attributes for entries. it also controls the entryCSN and entryUUID attributes, which are needed by the syncrepl provider. by default, lastmod is on. โœจ
  • lastbind on | off โ€” controls whether slapd will automatically maintain the pwdLastSuccess attribute for entries. by default, lastbind is off. on a replication consumer the pwdLastSuccess attribute will be forwarded to the provider assuming updateref setting and chain overlay are appropriately configured. ๐Ÿ”ฅ
  • lastbind-precision <integer> โ€” if lastbind is enabled, specifies how frequently pwdLastSuccess will be updated. more than integer seconds must have passed since the last successful bind. in a replicated environment with frequent bind activity it may be useful to set this to a large value. on a backend, if set to 0 (the default), the value set on the frontend is used. ๐Ÿ•ฐ๏ธ
  • limits <selector> <limit> [<limit> [...]] โ€” specify time and size limits based on the operation's initiator or base DN. the argument <selector> can be any of
anonymous | users | [<dnspec>=]<pattern> |
group[/oc[/at]]=<pattern>

with

<dnspec> ::= dn[.<type>][.<style>]

<type>  ::= self | this
<style> ::= exact | base | onelevel | subtree | children |
regex | anonymous

DN type self is the default and means the bound user ๐Ÿ’, while this means the base DN of the operation. The term anonymous matches all unauthenticated clients, and users matches all authenticated clients โ€” otherwise an exact dn pattern is assumed, unless you qualify it. Qualify the (optional) key string dn with:

  • exact or base (yes bestie, they're synonyms ๐Ÿ‘ฏ) to require an exact match
  • onelevel to require exactly one level of depth match
  • subtree to allow any level of depth match, including the exact match
  • children to allow any level of depth match, not including the exact match
  • regex to explicitly require the (default) match based on POSIX (''extended'') regular expression pattern

Finally, anonymous matches unbound operations; the pattern field is literally ignored ๐Ÿ™ˆ. You get the same behavior using the anonymous form of the <selector> clause. The term group, with the optional objectClass oc and attributeType at fields, followed by pattern, sets the limits for any DN listed in the values of the at attribute (default member) of the oc group objectClass (default groupOfNames) whose DN exactly matches pattern.

The currently supported limits are size and time โœจ


โฐ time limits

The syntax for time limits is time[.{soft|hard}]=<integer>, where integer is the number of seconds slapd will spend answering a search request. If no time limit is explicitly requested by the client, the soft limit is used ๐ŸŒธ. If the requested time limit exceeds the hard limit, the value of the limit is used instead. If the hard limit is set to the keyword soft, the soft limit is used in either case; if it's set to the keyword unlimited, no hard limit is enforced, go off king ๐Ÿ‘‘. Explicit requests for time limits smaller or equal to the hard limit are honored. If no limit specifier is set, the value is assigned to the soft limit, and the hard limit is set to soft, to preserve the original behavior.

๐Ÿ“ size limits

The syntax for size limits is size[.{soft|hard|unchecked}]=<integer>, where integer is the maximum number of entries slapd will return answering a search request.

  • If no size limit is explicitly requested by the client, the soft limit is used.
  • If the requested size limit exceeds the hard limit, the value of the limit is used instead.
  • If the hard limit is set to the keyword soft, the soft limit is used in either case.
  • If it's set to the keyword unlimited, no hard limit is enforced.
  • Explicit requests for size limits smaller or equal to the hard limit are honored.

The unchecked specifier sets a limit on the number of candidates a search request is allowed to examine. The rationale behind it ๐Ÿง : searches for non-properly indexed attributes may result in large sets of candidates, which must be examined by slapd(8) to determine whether they match the search filter or not. The unchecked limit gives you a way to drop such operations before they're even started ๐Ÿ’€. If the selected candidates exceed the unchecked limit, the search will abort with Unwilling to perform. If it's set to the keyword unlimited, no limit is applied (that's the default fr fr). If it's set to disabled, the search is not even performed; this can be used to disallow searches for a specific set of users. If no limit specifier is set, the value is assigned to the soft limit, and the hard limit is set to soft, to preserve the original behavior.

In case of no match, the global limits are used. The default values are the same as for sizelimit and timelimit; no limit is set on unchecked.

๐Ÿ—‚๏ธ pagedResults control limits

If pagedResults control is requested, the hard size limit is used by default, because the request of a specific page size is considered an explicit request for a limitation on the number of entries to be returned. However, the size limit applies to the total count of entries returned within the search, and not to a single page ๐Ÿ“„.

Additional size limits may be enforced; the syntax is:

size.pr={<integer>|noEstimate|unlimited}

where integer is the max page size if no explicit limit is set; the keyword noEstimate inhibits the server from returning an estimate of the total number of entries that might be returned (note: the current implementation does not return any estimate ๐Ÿ‘€). The keyword unlimited indicates that no limit is applied to the pagedResults control page size.

The syntax:

size.prtotal={<integer>|hard|unlimited|disabled}

lets you set a limit on the total number of entries that the pagedResults control will return. By default it's set to the hard limit, which will use the size.hard value. When set, integer is the max number of entries that the whole search with pagedResults control can return. Use unlimited to allow unlimited number of entries to be returned, e.g. to allow the use of the pagedResults control as a means to circumvent size limitations on regular searches; the keyword disabled disables the control, i.e. no paged results can be returned ๐Ÿšซ. Note that the total number of entries returned when the pagedResults control is requested cannot exceed the hard size limit of regular searches unless extended by the prtotal switch.

The limits statement is typically used to let an unlimited number of entries be returned by searches performed with the identity used by the consumer for synchronization purposes by means of the RFC 4533 LDAP Content Synchronization protocol (see syncrepl for details).

When using subordinate databases, it is necessary for any limits that are to be applied across the parent and its subordinates to be defined in both the parent and its subordinates. Otherwise the settings on the subordinate databases are not honored โ€” no cap, they just get ignored ๐Ÿซ .


maxderefdepth depth

Specifies the maximum number of aliases to dereference when trying to resolve an entry, used to avoid infinite alias loops ๐ŸŒ€. The default is 15.

multiprovider on | off

This option puts a consumer database into Multi-Provider mode. Update operations will be accepted from any user, not just the updatedn. The database must already be configured as a syncrepl consumer before this keyword may be set. This mode also requires a serverID (see above ๐Ÿ‘†) to be configured. By default, multiprovider is off.

monitoring on | off

This option enables database-specific monitoring in the entry related to the current database in the "cn=Databases,cn=Monitor" subtree of the monitor database, if the monitor database is enabled ๐Ÿ”. Currently, only the MDB database provides database-specific monitoring. If monitoring is supported by the backend it defaults to on, otherwise off.

overlay overlay-name

Add the specified overlay to this database. An overlay is a piece of code that intercepts database operations in order to extend or change them โœจ. Overlays are pushed onto a stack over the database, and so they will execute in the reverse of the order in which they were configured and the database itself will receive control last of all. See the slapd.overlays(5) manual page for an overview of the available overlays.

Note that all of the database's regular settings should be configured before any overlay settings.

readonly on | off

This option puts the database into "read-only" mode ๐Ÿ”’. Any attempts to modify the database will return an "unwilling to perform" error. By default, readonly is off.

restrict oplist

Specify a whitespace separated list of operations that are restricted. If defined inside a database specification, restrictions apply only to that database, otherwise they are global ๐ŸŒ. Operations can be any of:

  • add
  • bind
  • compare
  • delete
  • extended[=<OID>]
  • modify
  • rename
  • search

โ€ฆor the special pseudo-operations read and write, which respectively summarize read and write operations. The use of restrict write is equivalent to readonly on (see above). The extended keyword allows one to indicate the OID of the specific operation to be restricted. Unlike restrictop, this applies to everyone, including rootdn ๐Ÿ˜ค.

restrictop oplist [control=<oid>] (by <who> <allow|reject|drop control=<oid>> [stop|continue|break])+

Specify rules what operation types and control combinations are allowed and by whom. If defined inside a database specification, restrictions apply only to that database and override any global ones. This option shares a lot of its syntax and intent with access rules (slapd.access(5)). They are processed in order and if a line matches, no further rules are considered unless a matching by clause specifies a break rule ๐Ÿ›‘. The drop control=<oid> rule is notable in that it will act as reject if the specified control is provided by the client and is marked critical, otherwise it masks that control, including from the following restrictop lines. Dropping a control might not completely avoid it having impact โ€” this is implementation dependent, as some control processing happens before this step ๐Ÿ™ƒ.

Operations are the same as in the restrict keyword, which are tested first and apply indiscriminately.

rootdn dn

Specify the distinguished name that is not subject to access control or administrative limit restrictions for operations on this database ๐Ÿ‘‘. This DN may or may not be associated with an entry. An empty root DN (the default) specifies no root access is to be granted. It is recommended that the rootdn only be specified when needed (such as when initially populating a database). If the rootdn is within a namingContext (suffix) of the database, a simple bind password may also be provided using the rootpw directive. Many optional features, including syncrepl, require the rootdn to be defined for the database ๐Ÿ’–.

rootpw password

okay so this one sets a password โ€” or a hash of a password, queen behavior โ€” for the rootdn. ๐Ÿ’…

Big important catch tho: you can only set it if the rootdn actually lives inside the namingContext (aka the suffix) of that database. No sneaking in otherwise.

It accepts every RFC 2307 userPassword format the server knows about (peep the password-hash description for the receipts) plus plain cleartext. And yes, slappasswd(8) is literally right there to generate a hash for you. โœจ

ngl, cleartext and {CRYPT} passwords are not recommended. Like, please don't.

If you leave it empty โ€” which is the default โ€” then authentication of the root DN happens by other means (e.g. SASL). And SASL? encouraged. periodt. ๐Ÿ’–


suffix dn suffix

This specifies the DN suffix of the queries that get passed to this backend database. ๐ŸŽ€

You can give multiple suffix lines, and at least one is required for every single database definition. Non-negotiable.

If the suffix of one database is "inside" the suffix of another, the database with the inner suffix has to come first in the config file. Order matters bestie!! And you might also wanna glue those databases together with the subordinate keyword. ๐Ÿซถ


subordinate [advertise]

This says: hey, the current backend database is a subordinate of another backend database. A subordinate database may have only one suffix. You use this to glue multiple databases into a single namingContext. โœจ

So if the suffix of the current database is within the namingContext of a superior database, searches against the superior database get propagated down to the subordinate too. And all the databases associated with one single namingContext should have identical rootdns โ€” matching, cute, coordinated. ๐Ÿ‘‘

Behavior of other LDAP operations is not affected by this setting. Specifically: it is not possible to use moddn to move an entry from one subordinate to another subordinate within the namingContext. Nope. Can't do it. ๐Ÿ™ˆ

If you supply the optional advertise flag, the naming context of this database gets advertised in the root DSE. The default is to hide this database context, so that only the superior context is visible.

If the slap tools slapcat(8), slapadd(8), slapmodify(8), or slapindex(8) are used on the superior database, any glued subordinates that support these tools are opened as well. ๐Ÿ“‚

Databases that are glued together should usually be configured with the same indices (assuming they support indexing), even for attributes that only exist in some of these databases. In general, all glued databases should be configured as similarly as possible, because the whole intent here is to give the appearance of a single directory. main character illusion energy. ๐Ÿ’ซ

heads up bestie: the subordinate functionality is implemented internally by the glue overlay, so its behavior will interact with other overlays in use. By default, the glue overlay is automatically configured as the last overlay on the superior backend. Its position on the backend can be explicitly configured by setting an overlay glue directive at the desired position.

This explicit config is necessary e.g. when using the syncprov overlay, which needs to follow glue in order to work over all of the glued databases. Like, for example:

database mdb
suffix dc=example,dc=com
...
overlay glue
overlay syncprov

sync_use_subentry

Stores the syncrepl contextCSN in a subentry instead of in the context entry of the database. The subentry's RDN will be "cn=ldapsync". ๐ŸŒธ

By default, the contextCSN is stored in the context entry. That's it, that's the whole vibe.


syncrepl

syncrepl rid=<replica ID> provider=ldap[s]://<hostname>[:port]
       searchbase=<base DN> [type=refreshOnly|refreshAndPersist]
       [interval=dd:hh:mm:ss] [retry=[<retry interval> <# of retries>]+]
       [filter=<filter str>] [scope=sub|one|base|subord] [attrs=<attr
       list>] [exattrs=<attr list>] [attrsonly] [sizelimit=<limit>]
       [timelimit=<limit>] [schemachecking=on|off]
       [network-timeout=<seconds>] [timeout=<seconds>]
       [tcp-user-timeout=<milliseconds>] [bindmethod=simple|sasl]
       [binddn=<dn>] [saslmech=<mech>] [authcid=<identity>]
       [authzid=<identity>] [credentials=<passwd>] [realm=<realm>]
       [secprops=<properties>] [keepalive=<idle>:<probes>:<interval>]
       [starttls=yes|critical] [tls_cert=<file>] [tls_key=<file>]
       [tls_cacert=<file>] [tls_cacertdir=<path>]
       [tls_reqcert=never|allow|try|demand]
       [tls_reqsan=never|allow|try|demand] [tls_cipher_suite=<ciphers>]
       [tls_ecname=<names>] [tls_crlcheck=none|peer|all]
       [tls_protocol_min=<major>[.<minor>]] [suffixmassage=<real DN>]
       [logbase=<base DN>] [logfilter=<filter str>]
       [syncdata=default|accesslog|changelog] [lazycommit]

This makes the current database a consumer that gets kept up-to-date with the provider's content by setting up the current slapd(8) as a replication consumer site running a syncrepl replication engine. ๐Ÿ”ฅ

The consumer content stays synchronized to the provider content using the LDAP Content Synchronization protocol. For all the deep-dive setup deets on running a replicated slapd directory service with the syncrepl replication engine, go read the "OpenLDAP Administrator's Guide". ๐Ÿ“–

  • rid identifies the current syncrepl directive within the replication consumer site. It's a non-negative integer, not greater than 999 โ€” yeah, limited to three decimal digits. No more. ๐ŸŽ€
  • provider specifies the replication provider site that holds the provider content, as an LDAP URI. If <port> isn't given, the standard LDAP port number (389 or 636) is used.

The content of the syncrepl consumer is defined using a search specification as its result set. The consumer slapd will send search requests to the provider slapd according to that search specification. The search spec includes the searchbase, scope, filter, attrs, attrsonly, sizelimit, and timelimit parameters, just like in the normal search specification. ๐Ÿฆ‹

The exattrs option can also be used to specify attributes that should be omitted from incoming entries.

Defaults, since everyone asks:

  • scope defaults to sub
  • filter defaults to (objectclass=*)
  • there is no default searchbase
  • the attrs list defaults to "*,+" โ€” that returns all user and operational attributes
  • attrsonly and exattrs are unset by default
  • sizelimit and timelimit only accept "unlimited" and positive integers, and both default to "unlimited"

The sizelimit and timelimit parameters define a consumer-requested limitation on the number of entries that can be returned by the LDAP Content Synchronization operation. Leave these alone at the default โ€” otherwise replication may never succeed. ๐Ÿ’€

note tho: any provider-side limits for the replication identity will be enforced by the provider regardless of the limits requested by the LDAP Content Synchronization operation, much like for any other search operation. Provider said what it said.

The LDAP Content Synchronization protocol has two operation types:

  1. In the refreshOnly operation, the next synchronization search operation is periodically rescheduled at an interval time (specified by the interval parameter; 1 day by default) after each synchronization operation finishes.
  2. In the refreshAndPersist operation, a synchronization search remains persistent in the provider slapd. Further updates to the provider will generate searchResultEntry to the consumer slapd as the search responses to the persistent synchronization search.

If the initial search fails due to an error, the next synchronization search operation is periodically rescheduled at an interval time (specified by the interval parameter; 1 day by default).

If an error occurs during replication, the consumer will attempt to reconnect according to the retry parameter, which is a list of <retry interval> and <# of retries> pairs. For example, retry="60 10 300 3" means the consumer retries every 60 seconds for the first 10 times, then retries every 300 seconds for the next 3 times before it stops retrying. ๐Ÿ”

The + in <# of retries> means an indefinite number of retries until success. If no retry is specified, by default syncrepl retries every hour forever. iconic commitment honestly. ๐Ÿ’–

Schema checking can be enforced at the LDAP Sync consumer site by turning on the schemachecking parameter. The default is off. Schema checking on means that replicated entries:

  • must have a structural objectClass
  • must obey objectClass requirements in terms of required/allowed attributes
  • and naming attributes and distinguished values must be present

As a consequence, schema checking should be off when partial replication is used. ๐Ÿ‘‘

The network-timeout parameter sets how long the consumer will wait to establish a network connection to the provider. Once a connection is established, the timeout parameter determines how long the consumer will wait for the initial Bind request to complete. The defaults for these parameters come from ldap.conf(5).

The tcp-user-timeout parameter, if non-zero, corresponds to the TCP_USER_TIMEOUT set on the target connections, overriding the operating system setting. โฑ๏ธ Only some systems support the customization of this parameter โ€” it's ignored otherwise and system-wide settings are used.

So a bindmethod of simple is out here needing both binddn and credentials, and honestly bestie, only reach for it when you've got adequate security services actually in place (TLS or IPSEC, like, please ๐Ÿ™). REMEMBER: simple bind credentials must be in cleartext! Like, literally exposed. No cap. ๐Ÿ˜ญ

A bindmethod of sasl needs the saslmech option. Depending on the mechanism, you can pass an authentication identity and/or credentials with authcid and credentials. The authzid parameter is there if you wanna specify an authorization identity. And if you want specific security properties for a SASL bind (same vibes as the sasl-secprops keyword from up above โœจ), that's the secprops option. A non-default SASL realm? That's realm. ๐ŸŽ€

The identity used for synchronization by the consumer should be allowed to receive an unlimited number of entries in response to a search request. The provider, besides letting that syncrepl identity authenticate, should grant it appropriate access privileges to the data being replicated (that's the access directive), plus appropriate time and size limits. You can do this by either allowing unlimited sizelimit and timelimit, or by setting an appropriate limits statement in the consumer's configuration (go peek at sizelimit and limits for the deets ๐Ÿ‘€).

The keepalive parameter sets the values of idle, probes, and interval used to check whether a socket is alive:

  • idle โ€” how many seconds a connection needs to stay idle before TCP starts sending keepalive probes
  • probes โ€” the max number of keepalive probes TCP should send before it just drops the connection ๐Ÿ’€
  • interval โ€” the interval, in seconds, between individual keepalive probes
Only some systems support customizing these values. The keepalive parameter is ignored otherwise, and system-wide settings get used instead.

The starttls parameter specifies use of the StartTLS extended operation to establish a TLS session before Binding to the provider. If the critical argument is supplied, the session will be aborted if the StartTLS request fails. Otherwise the syncrepl session just keeps going without TLS (living dangerously, honestly ๐Ÿซฃ). The tls_reqcert setting defaults to "demand", the tls_reqsan setting defaults to "allow", and the other TLS settings default to the same as the main slapd TLS settings.

The suffixmassage parameter lets the consumer pull entries from a remote directory whose DN suffix is different from the local directory. The portion of the remote entries' DNs that matches the searchbase gets replaced with the suffixmassage DN. Slay, seamless remapping. ๐Ÿ’…


Now the plot twist: instead of replicating whole entries, the consumer can query logs of data modifications. This mode is called delta syncrepl. ๐Ÿ”ฅ On top of all the parameters above, you also need logbase and logfilter set properly for the log you're gonna use. And the syncdata parameter must be set to either "accesslog" if the log conforms to the slapo-accesslog(5) log format, or "changelog" if the log conforms to the obsolete changelog format. If syncdata is omitted or set to "default", then the log parameters are ignored. And if multiprovider is in play, the same logbase database must be configured on all of the providers. (Everyone's gotta be on the same page, fr fr.)

The lazycommit parameter tells the underlying database that it can store changes without performing a full flush after each change. Cool for performance on the consumer side โ€” but it's trading away safety or durability to get there. โš ๏ธ

  • updatedn <dn> โ€” only applicable in a replica database. It specifies the DN permitted to update (subject to access controls) the replica. It's only needed in certain push-mode replication scenarios. And generally, this DN should not be the same as the rootdn used at the provider. ๐Ÿšซ
  • updateref <url> โ€” specifies the referral to pass back when slapd(8) is asked to modify a replicated local database. If specified multiple times, each url is provided.

๐Ÿฆ‹ DATABASE-SPECIFIC OPTIONS ๐Ÿฆ‹

Every database gets to have its own specific configuration options, and those are documented separately in the backends' manual pages. Check slapd.backends(5) for the overview of which backends are even available. ๐Ÿ‘‘

๐ŸŒˆ EXAMPLES ๐ŸŒˆ

Here's a short lil example of a configuration file, bestie โ€” copy it, love it, adapt it:

include   /etc/openldap/schema/core.schema
pidfile   /var/lib/openldap/run/slapd.pid

# Subtypes of "name" (e.g. "cn" and "ou") with the
# option ";x-hidden" can be searched for/compared,
# but are not shown.  See slapd.access(5).
attributeoptions x-hidden lang-
access to attrs=name;x-hidden by * =cs

# Protect passwords.  See slapd.access(5).
access    to attrs=userPassword  by * auth
# Read access to other attributes and entries.
access    to *  by * read

database  mdb
suffix    "dc=our-domain,dc=com"
# The database directory MUST exist prior to
# running slapd AND should only be accessible
# by the slapd/tools. Mode 0700 recommended.
directory /var/lib/openldap/openldap-data
# Indices to maintain
index     objectClass  eq
index     cn,sn,mail   pres,eq,approx,sub

# We serve small clients that do not handle referrals,
# so handle remote lookups on their behalf.
database  ldap
suffix    ""
uri       ldap://ldap.some-server.com/
lastmod   off

The "OpenLDAP Administrator's Guide" has a longer, annotated example of a configuration file if you want the director's cut. And the original /etc/openldap/slapd.conf is another example. ๐ŸŒธ

๐Ÿ“ FILES ๐Ÿ“

  • /etc/openldap/slapd.conf โ€” the default slapd configuration file

๐Ÿ’œ SEE ALSO ๐Ÿ’œ

ldap(3), gnutls-cli(1), slapd-config(5), slapd.access(5), slapd.backends(5), slapd.overlays(5), slapd.plugin(5), slapd(8), slapacl(8), slapadd(8), slapauth(8), slapcat(8), slapdn(8), slapindex(8), slapmodify(8), slappasswd(8), slaptest(8).

"OpenLDAP Administrator's Guide" (http://www.OpenLDAP.org/doc/admin/)

๐Ÿ‘‘ ACKNOWLEDGEMENTS ๐Ÿ‘‘

OpenLDAP Software is developed and maintained by The OpenLDAP Project <http://www.openldap.org/>. OpenLDAP Software is derived from the University of Michigan LDAP 3.3 Release.


And that's the whole page, bestie โ€” you made it all the way to the end, main character energy, genuinely iconic. ๐Ÿฅน๐Ÿ’– This party was brought to you by OpenLDAP 2.7.2, dated 2026/10/21, and it's the manual for SLAPD.CONF(5). Go forth and configure responsibly. Periodt. ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from