SLAPD-CONFIG(5)
π SLAPD-CONFIG π
okay bestie, buckle up, this is SLAPD-CONFIG(5) from the File Formats Manual and it's the configuration backend of slapd β yes THE one. sit down, get a snack, we're doing this properly π
β¨ NAME β¨
slapd-config β the configuration backend to slapd, no cap πββοΈ
β¨ SYNOPSIS β¨
/etc/openldap/slapd.d
β¨ DESCRIPTION β¨
so. the config backend is the one that manages all of the configuration info for the slapd(8) daemon. like, all of it. and bestie, it's not just slapd using it β the SLAPD tools slapacl(8), slapadd(8), slapauth(8), slapcat(8), slapdn(8), slapindex(8), slapmodify(8), and slaptest(8) all read this same config info too. it's giving "everyone's shared notes doc" energy π
the config backend is backward compatible with the older slapd.conf(5) file, BUT (and this is the iconic part) it gives you the ability to change the configuration dynamically at runtime. the way that works:
- if
slapdis run with only aslapd.conffile, dynamic changes are allowed... but they will not persist across a server restart π - dynamic changes are only saved when
slapdis running from aslapd.dconfiguration directory π
unlike other backends, there can only be one instance of the config backend, and most of its structure is predefined. the root of the database is hardcoded to cn=config, and this root entry holds global settings for slapd. multiple child entries underneath the root entry carry all the other settings:
cn=Moduleβ dynamically loaded modulescn=Schemaβ schema definitionsolcBackend=xxxβ backend-specific settingsolcDatabase=xxxβ database-specific settings
the cn=Module entries only show up in configurations where slapd was built with support for dynamically loaded modules. there can be multiple entries β one for each configured module path. within each entry there will be values recorded for each module loaded on a given path. these entries have no children. (childless, free, unbothered β¨)
the cn=Schema entry contains all of the hardcoded schema elements. the children of this entry contain all user-defined schema elements. for schema that were loaded from include files, the child entry will be named after the include file from which the schema was loaded. typically the first child in this subtree will be cn=core,cn=schema,cn=config.
olcBackend entries are for storing settings specific to a single backend type β and thus global to all database instances of that type. at present, only back-mdb implements any options of this type, so this setting is not needed for any other backends. don't come for me, that's just what it says π
olcDatabase entries store settings specific to a single database instance. these entries may have olcOverlay child entries corresponding to any overlays configured on the database. the olcDatabase and olcOverlay entries may also have miscellaneous child entries for other settings as needed. and here's the tea β there are two special database entries that are predefined:
- an entry for the config database itself
- an entry for the "frontend" database
settings in the frontend database are inherited by the other databases, unless they are explicitly overridden in a specific database. inherit like the family features bestie π§¬
the specific configuration options available are discussed below in the Global Configuration Options, General Backend Options, and General Database Options. options are set by defining LDAP attributes with specific values. in general, the names of the LDAP attributes are the same as the corresponding slapd.conf keyword, with an olc prefix added on. it's literally just their government name plus olc π
the parser for many of these attributes is the same as the one used for parsing the slapd.conf keywords. as such, slapd.conf keywords that allow multiple items to be specified on one line, separated by whitespace, will allow multiple items to be specified in one attribute value. however β and this is the plot twist β when reading the attribute via LDAP, the items will be returned as individual attribute values. one becomes many. character development π¦
backend-specific options are discussed in the slapd-<backend>(5) manual pages. refer to the "OpenLDAP Administrator's Guide" for more details on configuring slapd.
β¨ GLOBAL CONFIGURATION OPTIONS β¨
options described in this section apply to the server as a whole. arguments that should be replaced by actual text are shown in brackets <>.
β οΈ these options may only be specified in thecn=configentry. this entry must have an objectClass ofolcGlobal. no exceptions bestie, it says must π«Ά
olcAllows: <features>β specify a set of features to allow (default none). let's break it down, one flag at a time:bind_v2β allows acceptance of LDAPv2 bind requests. β οΈ note thatslapd(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).
olcArgsFile: <filename>β the (absolute) name of a file that will hold theslapdserver's command line (program name and options). like a receipt for how you launched it π§ΎolcAttributeOptions: <option-name>...β define tagging attribute options, or option tag/range prefixes. some rules, and bestie they are strict:- options must not end with
- - prefixes must end with
- - the
lang-prefix is predefined - if you use the
olcAttributeOptionsdirective,lang-will no longer be defined and you must specify it explicitly if you want it defined. yes, it will simply evaporate. be warned π
- options must not end with
an attribute description with a tagging option is a subtype of that attribute description without the option. except for that, options defined this way have no special semantics. prefixes defined this way work like the lang- options: they define a prefix for tagging options starting with the prefix. that is, 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. the range is ranging β¨
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 this is a transfer option, not a tagging option. don't mix them up, iykyk.
olcAuthIDRewrite: <rewrite-rule>β used by the authentication framework to convert simple user names to an LDAP DN used for authorization purposes. its purpose is analogous to that ofolcAuthzRegexp(see below). the rewrite-rule is a set of rules analogous to those described inslapo-rwm(5)for data rewriting (after stripping therwm-prefix). π¨olcAuthIDRewriteandolcAuthzRegexpshould not be intermixed. pick a lane bestie.olcAuthzPolicy: <policy>β used to specify which rules to use for Proxy Authorization. proxy authorization allows a client to authenticate to the server using one user's credentials, but specify a different identity to use for authorization and access control purposes. it essentially allows user A to login as user B, using user A's password. (main character behavior, lowkey)
the flags, and what they do:
noneβ disables proxy authorization. this is the default setting.fromβ will use rules in theauthzFromattribute of the authorization DN.toβ will use rules in theauthzToattribute of the authentication DN.anyβ an alias for the deprecated value ofboth, will allow any of the above, whatever succeeds first (checked into,fromsequence.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. protect it like your phone passcode, 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}
and now, the forms, explained one by one:
- 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 eitherauthzFromorauthzTo. - the second form is a DN, with the optional style modifiers
exact,onelevel,children, andsubtreefor exact, onelevel, children and subtree matches, which cause<pattern>to be normalized according to the DN normalization rules β or the specialregexstyle, which causes the<pattern>to be treated as a POSIX (''extended'') regular expression, as discussed inregex(7)and/orre_format(7). a pattern of*means any non-anonymous DN. (the*is giving "anyone but the empty DN, obviously" π) - the third form is a SASL id, with the optional fields
<mech>and<realm>that allow to specify a SASL mechanism, and eventually a SASL realm, for those mechanisms that support one. π£ heads up: the need to allow the specification of a mechanism is still debated, and users are strongly discouraged to rely on this possibility. - the fourth form is a group specification. it consists of the keyword
group, optionally followed by the specification of the groupobjectClassandattributeType. theobjectClassdefaults togroupOfNames. theattributeTypedefaults tomember. the group with DN<pattern>is searched with base scope, filtered on the specifiedobjectClass. the values of the resultingattributeTypeare searched for the asserted DN. - 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.
okay and that's only the beginning of the global options, because there are so many more where that came from... π
okay bestie, we were mid-thought about identity specs β let's finish that and then just keep rolling through the options, because there are so many and honestly they're all kinda iconic in their own way π
Since how authzFrom and authzTo get interpreted can literally affect security, everybody is strongly encouraged to just say out loud which type of identity specification they mean instead of leaving it vibes-based π. And a subset of these rules can also show up as the third arg in the olcAuthzRegexp statement (more on that literally right below), and the ones that specifically work there are the URI form β as long as it resolves to exactly one entry β plus the dn.exact:<dn> form. iykyk β¨
πΈ OPTIONS (cont'd) πΈ
olcAuthzRegexp: <match> <replace>β okay so this one is the authentication framework's little matchmaker π. Its whole job is converting simple user names into an LDAP DN for authorization purposes. Where do those simple names come from? From the SASL subsystem, or yanked out of certificates when it's cert-based SASL EXTERNAL, or handed over inside the RFC 4370 "proxied authorization" control. Important detail alert: the resulting DN does not have to point at an actual existing entry to count as valid β it's valid on principle, periodt.
So when an authorization request rolls in from the SASL subsystem, the SASL USERNAME, REALM, and MECHANISM get scooped up (when they're available) and squished together into a name that looks like:
UID=<username>[[,CN=<realm>],CN=<mechanism>],CN=auth
That name then gets compared against the match POSIX ("extended") regular expression, and if it matches? The name gets replaced with the replace string. Girl, it's giving find-and-replace but for identity π₯
If the match regex has wildcard strings wrapped in parentheses, like:
UID=([^,]*),CN=.*
then whatever matched that wildcard gets stashed in the numbered placeholder variable $1. Got more parenthesized wildcards? Those matches land in $2, $3, and so on, 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 β that's a string with the dn: prefix on it β or an LDAP URI. If it's a URI, the server goes and searches its own database(s) with it, and if that search comes back with exactly one entry, the name gets swapped out for the DN of that entry. The LDAP URI has to have no hostport, attrs, or extensions components, but the filter is mandatory, bestie, like:
ldap:///OU=Accounts,DC=example,DC=com??one?(UID=$1)
The protocol part of the URI has to be strictly ldap. And heads up π β this search is subject to access controls. Specifically, the authentication identity needs to have "auth" access in the subject. No auth, no DN, simple as that.
You can specify multiple olcAuthzRegexp values if you want multiple match-and-replace patterns. They get checked in the order they appear in the attribute, and it stops at the first successful match. First come, first served, no take-backs π
olcConcurrency: <integer>β this is your desired level of concurrency, handed down to the underlying thread system as a hint. That's it, just a hint π¦. The default is to not provide any hint at all. And btw this setting only means anything on certain platforms where user threads and kernel threads don't have a neat one-to-one correspondence. Vibe-based hinting, essentially.olcConnMaxPending: <integer>β the max number of pending requests allowed for an anonymous session. If requests come in faster than the server can chew through them, they queue up until they hit this limit. Exceed the limit? The session gets closed, sorry π«Ά. Default is100.olcConnMaxPendingAuth: <integer>β same energy as above but for an authenticated session. Default is1000. Logged-in besties get more patience, as they should πolcDisallows: <features>β here's your blocklist of features to disallow (default: none, we're permissive). The options are:bind_anonβ disables accepting anonymous bind requests. Careful though: this does not stop anonymous directory access (go read "require authc" for that part).bind_simpleβ disables simple (bind) authentication.tls_2_anonβ disables forcing the session to anonymous status upon StartTLS operation receipt (peeptls_authctoo).tls_authcβ disallows the StartTLS operation if authenticated (see alsotls_2_anon).proxy_authz_non_criticalβ disables acceptance of the proxied authorization control (RFC4370) when criticality is set to FALSE.dontusecopy_non_criticalβ disables acceptance of the dontUseCopy control (yes, it's a work in progress, we know π) when criticality is set to FALSE.
olcGentleHUP: { TRUE | FALSE }β a SIGHUP signal will only trigger a 'gentle' shutdown-attempt. Meaning: slapd stops listening for new connections, but does not close the connections to current clients π. Future write operations just return unwilling-to-perform though, so it's not a total free-for-all. Slapd terminates when all clients have closed their connections (if they ever do π) or, like before, if it catches a SIGTERM signal. This is genuinely useful if you wanna shut down the server and spin up a new slapd with a different database without disrupting the clients who are currently active. Default isFALSE. And you might wanna pair this witholcIdleTimeout, just saying πolcIdleTimeout: <integer>β how many seconds to wait before forcibly closing an idle client connection. Setting it to0disables the feature entirely. The default is0. And you may also wanna set theolcWriteTimeoutoption while you're at it, bestie πolcIndexHash64: { TRUE | FALSE }β use a 64 bit hash for indexing, otherwise 32 bit. The default is now 64 bit. These hashes get used for equality and substring indexing. The 64 bit version dodges index collisions once the number of indexed values passes ~64 million. (Quick note: substring indexing generates multiple index values per actual attribute value, so heads up on that math.) Indices generated with 32 bit hashes are incompatible with the 64 bit version, and vice versa β so any existing databases must be fully reindexed when you change this setting. And since 64 bit is now the default, this option is deprecated and will eventually be removed. Rip, king πolcIndexIntLen: <integer>β the key length for ordered integer indices. The most significant bytes of the binary integer get used for the index keys. Default is4, which gives you exact indexing for 31 bit values. For values that are too large, a floating point representation gets used to index them. Clever little workaround ngl β¨olcIndexSubstrIfMaxlen: <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 gets ignored, sorry to those characters π. Default is4.olcIndexSubstrIfMinlen: <integer>β the minimum length for subinitial and subfinal indices. An attribute value needs at least this many characters to even get processed by the indexing functions. Default is2.olcIndexSubstrAnyLen: <integer>β the length used for subany indices. An attribute value must have at least this many characters to be processed, and values longer than this get processed in segments of this length. Default is4. Also: the subany index gets used in subinitial and subfinal index lookups whenever the filter string is longer than theolcIndexSubstrIfMaxlenvalue. Multi-purpose icon behavior πolcIndexSubstrAnyStep: <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. Default is2. For example, with the default values, a search using this filter"cn=*abcdefgh*"would generate index lookups for"abcd","cdef", and"efgh". Sliding window slay π¦
Note: whether indexing support is even a thing depends on the particular backend in use. Also, changing these settings will generally require you to delete any indices that depend on these parameters and recreate them with slapindex(8). No shortcuts, bestie, that's the rule.
olcListenerThreads: <integer>β how many threads to use for the connection manager. The default is1, and honestly that's typically plenty for up to 16 CPU cores. Oh, and the value should be set to a power of 2, so keep it cute:1,2,4,8β¦ β¨olcLocalSSF: <SSF>β specifies the Security Strength Factor (SSF) given to local LDAP sessions, like the ones to theldapi://listener. For the whole explanation of SSF values, go peek at theolcSaslSecPropsminssfoption description. Default is71. πolcLogFile: <filename>β a file for recording slapd debug messages. Important: these messages are completely unrelated to the messages exposed by theolcLogLevelconfiguration parameter, don't mix them up π. This setting only affects the slapd daemon and does nothing to the command line tools. By default these messages only go to stderr and are not recorded anywhere else. If you specify a logfile, messages get copied to both stderr and the logfile. Two places, one message, no cap πolcLogFileFormat: debug|syslog-utc|syslog-localtime|rfc3339-utcβ the prefix format for messages written to the logfile. Thedebugformat is the normal format used for slapd debug messages β timestamp in hexadecimal, followed by a thread ID. The other options usesyslog(3)style prefixes, with timestamps either in UTC or in the local timezone. Default isdebugformat. Pick your aesthetic πolcLogFileOnly: TRUE | FALSEβ says that debug messages should only go to the configured logfile and not to stderr. Choose your loyalty πolcLogFileRotate: <max> <Mbytes> <hours>β automatic rotation for the configured logfile, specified as three things at once:- the maximum number of old logfiles to retain (
<max>) β must be in the range1β99, - a maximum size in megabytes a logfile can grow to before rotation (
<Mbytes>), - a maximum age in hours a logfile can be used before rotation (
<hours>).
- the maximum number of old logfiles to retain (
Setting Mbytes or hours to zero disables the size or age check respectively. But at least one of Mbytes or hours must be non-zero β you can't zero out both and expect rotation to happen, that's just not how it works bestie π. By default, no automatic rotation will be performed. Set it up or accept the ever-growing logfile, your call πΈ
olcLogLevel: <integer> [...]β okay bestie, this one sets the level at which debugging statements and operation statistics get syslogged (currently that goes to thesyslogd(8)LOG_LOCAL4facility). But plot twist: these are subsystems, not "bigger number = more yapping" log levels. Some messages with higher priority get logged no matter what your loglevel is, the absolute second any logging is configured at all. And the levels are additive. Here's the whole menu:1(0x1trace) β trace function calls2(0x2packets) β debug packet handling4(0x4args) β heavy trace debugging (function args)8(0x8conns) β connection management16(0x10BER) β print out packets sent and received32(0x20filter) β search filter processing64(0x40config) β configuration file processing128(0x80ACL) β access control list processing256(0x100stats) β connections, LDAP operations, results (recommended)512(0x200stats2) β stats2 log entries sent1024(0x400shell) β print communication with shell backends2048(0x800parse) β entry parsing16384(0x4000sync) β LDAPSync replication32768(0x8000none) β only messages that get logged whatever log level is set
You can hand slapd the level you want as a single integer that ORs your picks together (decimal or hexadecimal, your call π ), as a list of integers (which get ORed internally), or as a list of the names shown in those parentheses. So all of these are literally the same vibe:
olcLogLevel: 129
olcLogLevel: 0x81
olcLogLevel: 128 1
olcLogLevel: 0x80 0x1
olcLogLevel: acl trace
The keyword any is your shortcut to logging at all levels (it's equivalent to -1). The keyword none, or its equivalent integer representation, makes those messages that get logged regardless of the configured olcLogLevel actually log. And fr fr β if no olcLogLevel is defined (or it's a 0 level), no logging occurs at all, so you need at least the none level to even get your high-priority messages through.
not me dropping the boat:packets,BER, andparseare only available as debug output onstderrβ they do not get sent to syslog. π
This setting defaults to stats, and ngl you should usually keep stats in there when you stack on other loglevels, because it's what helps you actually analyze the logs. π
olcMaxFilterDepth: <integer>β sets the max depth of nested filters in search requests. Default is1000.olcMaxQtime: <integer>β the max time operations are allowed to sit in the queue before they execute, measured in microseconds. Anything that blows past this gets rejected with zero further processing. Default is0, which turns the check off.olcPasswordCryptSaltFormat: <format>β this one sets the format of the salt that gets passed tocrypt(3)when generating{CRYPT}passwords (peepolcPasswordHash) while processing LDAP Password Modify Extended Operations (RFC 3062).
The string has to be in sprintf(3) format and may include one (and only one π«Ά) %s conversion. That conversion gets swapped out for a string of random characters from [A-Za-z0-9./]. For example, "%.2s" gives you a two-character salt, and "$1$%.8s" tells some versions of crypt(3) to use an MD5 algorithm and hands over 8 random characters of salt. The default is "%s", which provides 31 characters of salt.
olcPidFile: <filename>β the (absolute) name of a file that holds the slapd server's process ID. Seegetpid(2).olcPluginLogFile: <filename>β the (absolute) name of a file that will contain log messages from SLAPI plugins. Seeslapd.plugin(5)for the details.olcReferral: <url>β the referral slapd hands back whenslapd(8)can't find a local database to handle a request. If you specify multiple values, each url gets provided.olcReverseLookup: TRUE | FALSEβ turn client name unverified reverse lookup on/off. Default isFALSEif compiled with--enable-rlookups.olcRootDSE: <file>β the name of anLDIF(5)file holding user defined attributes for the root DSE. These get returned in addition to the attributes slapd normally produces.
So what even is the root DSE? It's an entry with info about the server and its capabilities, in operational attributes. It has the empty DN, and you can read it with something like:
ldapsearch -x -b "" -s base "+"
See RFC 4512 section 5.1 for the lore β¨
olcSaslAuxprops: <plugin> [...]β tells slapd which auxprop plugins to use for authentication lookups. Default is empty, which just uses slapd's internal support. Usually you don't need any other auxprop plugins, periodt.olcSaslAuxpropsDontUseCopy: <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.olcSaslAuxpropsDontUseCopyIgnore TRUE | FALSEβ used to disable replication of the attribute(s) defined byolcSaslAuxpropsDontUseCopyand instead use a local value for the attribute. This lets the SASL mechanism keep working if the provider is offline. Heads up though, this can cause replication inconsistency. Defaults toFALSE.olcSaslHost: <fqdn>β used to specify the fully qualified domain name used for SASL processing.olcSaslRealm: <realm>β specify the SASL realm. Default is empty.olcSaslCbinding: none | tls-unique | tls-endpointβ specify the channel-binding type. See alsoLDAP_OPT_X_SASL_CBINDING. Default isnone.olcSaslSecProps: <properties>β used to specify Cyrus SASL security properties. Grab a snack, there's a bunch π- The
noneflag (with no other properties) causes the flag properties default,"noanonymous,noplain", to be cleared. - The
noplainflag disables mechanisms susceptible to simple passive attacks. - The
noactiveflag disables mechanisms susceptible to active attacks. - The
nodictflag disables mechanisms susceptible to passive dictionary attacks. - The
noanonymousflag disables mechanisms which support anonymous login. - The
forwardsecflag requires forward secrecy between sessions. - The
passcredrequires mechanisms which pass client credentials (and allows mechanisms which can pass credentials to do so). - The
minssf=<factor>property specifies the minimum acceptable security strength factor as an integer approximate to effective key length used for encryption.0(zero) implies no protection,1implies integrity protection only,128allows RC4, Blowfish and other similar ciphers,256will require modern ciphers. The default is0. - The
maxssf=<factor>property specifies the maximum acceptable security strength factor as an integer (seeminssfdescription). The default isINT_MAX. - The
maxbufsize=<size>property specifies the maximum security layer receive buffer size allowed.0disables security layers. The default is65536.
- The
olcServerID: <integer> [<URL>]β give this server an integer ID from0to4095. You can also hand it over as a hexadecimal ID by slapping"0x"in front of the value. Non-zero IDs are required when you're doing multi-provider replication, and each provider needs its own unique non-zero ID. And this requirement also applies to separate providers contributing to a glued set of databases, iykyk. If you provide the URL, this directive can be specified multiple times, giving a complete list of participating servers and their IDs. You should use the fully qualified hostname of each server in the supplied URLs. These IDs show up in the"replica id"field of all CSNs generated by the specified server. The default value is zero, and that's only valid for single provider replication. Example:
olcServerID: 1 ldap://ldap1.example.com
olcServerID: 2 ldap://ldap2.example.com
olcSockbufMaxIncoming: <integer>β the maximum incoming LDAP PDU size for anonymous sessions. Default is262143.olcSockbufMaxIncomingAuth: <integer>β the maximum incoming LDAP PDU size for authenticated sessions. Default is4194303.olcTCPBuffer [listener=<URL>] [{read|write}=]<size>β sets the size of the TCP buffer. A global value for both the read and write TCP buffers related to any listener gets defined, unless the listener is explicitly specified, or either thereadorwritequalifiers are used. Seetcp(7)for the deets. Oh and heads up: some OS-es implement automatic TCP buffer tuning, so vibe check your platform πolcThreads: <integer>β the maximum size of the primary thread pool. Default is16; minimum value is2.olcThreadQueues: <integer>β the number of work queues to use for the primary thread pool. Default is1, and that's typically adequate for up to 8 CPU cores. The value should not exceed the number of CPUs in the system.olcToolThreads: <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 is1.olcWriteTimeout: <integer>β how many seconds to wait before forcibly closing a connection that has an outstanding write. This lets you recover from all kinds of network hang conditions. A setting of0disables the feature. Default is0.
β¨ TLS OPTIONS β¨
So if your slapd was built with support for Transport Layer Security (aka TLS, aka the thing that makes your LDAP traffic not readable by every random person on the wifi π), there are more options you can specify. And bestie, there are a LOT of them. Buckle up.
olcTLSCipherSuite:<cipher-suite-spec> β lets you configure what ciphers will be accepted and in what preference order. Your <cipher-suite-spec> should be a cipher specification for whichever TLS library you're actually using (OpenSSL or GnuTLS). Heads up though: this directive is not supported when using MbedTLS. π
Example time, and yes they're different for each library:
OpenSSL:
olcTLSCipherSuite: HIGH:MEDIUM:+SSLv2
GnuTLS:
olcTLSCiphersuite: SECURE256:!AES-128-CBC
Wanna check what ciphers a given spec actually selects in OpenSSL? Run this:
openssl ciphers -v <cipher-suite-spec>
With GnuTLS, the available specs live in the manual page of gnutls-cli(1) β go look at the description of the --priority option. And in older versions of GnuTLS, where gnutls-cli doesn't support --priority at all, you can get the β more limited β list of ciphers by calling:
gnutls-cli -l
olcTLSCACertificateFile:<filename> β specifies the file that contains certificates for all of the Certificate Authorities thatslapdwill recognize. The certificate for the CA that signed the server certificate must be included among these certificates. And if the signing CA was not a top-level (root) CA, then certificates for the entire sequence of CA's from the signing CA all the way up to the top-level CA should be present. Multiple certificates are simply appended to the file β and no, the order is not significant, so don't stress π«ΆolcTLSCACertificatePath:<path> β specifies the path of directories containing Certificate Authority certificates, each in its own separate individual file. Usually you define only one of this orolcTLSCACertificateFile. But if you specify both, both locations will be used, periodt. Multiple directories may be specified, separated by a semi-colon.olcTLSCACertificate:<CA cert> β stores a single CA certificate that will be trusted by the server, in DER format. If this option is set, theolcTLSCACertificateFileandolcTLSCACertificatePathoptions are ignored. And if you need multiple CA certificates? Then you must useolcTLSCACertificateFileorolcTLSCACertificatePathinstead of this one, no cap.olcTLSCertificateFile:<filename> β specifies the file that contains theslapdserver certificate.
When using OpenSSL, that file may also contain any number of intermediate certificates after the server certificate. π
olcTLSCertificate:<cert> β stores a single certificate for the server, in DER format. If this option is used, theolcTLSCertificateFileoption is ignored.olcTLSCertificateKeyFile:<filename> β specifies the file that contains theslapdserver private key that matches the specified server certificate. Now listen: if the private key file is protected with a password, the password must be manually typed in whenslapdstarts. π Usually the private key is not protected with a password, so thatslapdcan start without manual intervention β which means it is of critical importance that you protect that file carefully.
bestie. protect the key file. i am begging. π¨
olcTLSCertificateKey:<key> β stores the private key that matches the server certificate. If this option is used, theolcTLSCertificateKeyFileoption is ignored.olcTLSDHParamFile:<filename> β specifies the file that contains 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.
Note that 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 no protection against man-in-the-middle attacks. You should append "!ADH" to your cipher suites to ensure that these suites are not used. This directive is not supported when using MbedTLS.
olcTLSECName:<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 β with GnuTLS the curves may be chosen in the GnuTLS ciphersuite specification instead.olcTLSProtocolMin:<major>[.<minor>]β specifies 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. To require TLS 1.x or higher, set this option to3.(x+1). Like so:
olcTLSProtocolMin: 3.2
That would require TLS 1.1. If you specify a minimum higher than what the OpenLDAP implementation supports, it'll just require the highest level that it does support. This directive is ignored with GnuTLS.
olcTLSRandFile:<filename> β specifies the file to obtain random bits from when/dev/[u]randomis not available. Generally set to the name of the EGD/PRNGD socket. The environment variableRANDFILEcan also be used to specify the filename. This directive is ignored with GnuTLS.olcTLSVerifyClient:<level> β specifies what checks to perform on client certificates in an incoming TLS session, if any. The <level> can be specified as one of these keywords:neverβ this is the default.slapdwill 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.
Also: a valid client certificate is required in order to use the SASL EXTERNAL authentication mechanism with a TLS session. As such, a non-default olcTLSVerifyClient setting must be chosen to enable SASL EXTERNAL authentication. ikyk π
olcTLSCRLCheck:<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 theolcTLSCACertificatePathparameter to be set. This parameter is ignored with GnuTLS. <level> can be specified as one of these keywords:noneβ no CRL checks are performedpeerβ check the CRL of the peer certificateallβ check the CRL for a whole certificate chain
olcTLSCRLFile:<filename> β specifies a file containing a Certificate Revocation List to be used for verifying that certificates have not been revoked. This parameter is only valid when using GnuTLS.
π§ DYNAMIC MODULE OPTIONS π§
So if slapd is compiled with --enable-modules then the module-related entries will be available, bestie. These entries are named
cn=module{x},cn=config
and they must have the olcModuleList objectClass. You should create one entry per olcModulePath. Normally the config engine generates the "{x}" index in the RDN automatically, so it can be omitted when you're initially loading these entries. β¨
olcModuleLoad:<filename>[<arguments>...]β specify the name of a dynamically loadable module to load, plus any additional arguments if the module supports them. The filename may be an absolute path name or just a simple filename. Non-absolute names are searched for in the directories specified by theolcModulePathoption. πolcModulePath:<pathspec> β specify a list of directories to search for loadable modules. Typically the path is colon-separated, but honestly that depends on the operating system. The default is/usr/lib/openldap, which is where the standard OpenLDAP install will place its modules. π
β¨ SCHEMA OPTIONS β¨
So schema stuff lives in its own little corner of the universe, bestie β every schema definition is created as an entry inside the cn=schema,cn=config subtree, and those entries have to carry the olcSchemaConfig objectClass. And like we already mentioned up above, the actual cn=schema,cn=config entry is predefined, so anything you try to specify for it just gets ignored. It said what it said. π
olcAttributetypesβ defines a whole attribute type, using the LDAPv3 syntax from RFC 4512. The slapd parser is a little extra (affectionate) and 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. (Peep theolcObjectIdentifierdescription for the tea on that.)
olcAttributetypes: ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE]
[SUP <oid>] [EQUALITY <oid>] [ORDERING <oid>] [SUBSTR <oid>]
[SYNTAX <oidlen>] [SINGLE-VALUE] [COLLECTIVE]
[NO-USER-MODIFICATION] [USAGE <attributeUsage>] )
olcDitContentRulesβ sets up a DIT Content Rule, again with the LDAPv3 syntax from RFC 4512. Same deal as above: slapd's parser flexes by accepting string forms and numeric OIDs for the attribute OID and the attribute syntax OID. (SeeolcObjectIdentifier, iykyk.)
olcDitContentRules: ( <oid> [NAME <name>] [DESC <description>]
[OBSOLETE] [AUX <oids>] [MUST <oids>] [MAY <oids>] [NOT <oids>] )
olcLdapSyntaxesβ defines an LDAP syntax with the LDAPv3 syntax from RFC 4512. Once again the parser is like "numeric OIDs? string forms? both slay," for the syntax OID. (Check theobjectidentifierdescription.) π¦
Now this next bit is the moment: the slapd parser also honors the X-SUBST extension (that's an OpenLDAP-specific thing, not standard), which lets you use the olcLdapSyntaxes attribute to define a syntax that isn't implemented, alongside another syntax β the extension's value, substitute-syntax β which acts as its temporary replacement. That substitute-syntax has to be defined, no exceptions. Why bother? So you can define attribute types that make use of non-implemented syntaxes while still using the correct syntax OID. And fr fr, unless you use X-SUBST, this configuration statement would just throw an error, because likeβ¦ no handlers would be associated with the resulting syntax structure. Nothing to hold it up. π
olcLdapSyntaxes ( <oid> [DESC <description>] [X-SUBST <substitute-syntax>] )
olcObjectClassesβ defines an objectclass using the LDAPv3 syntax from RFC 4512. The parser's little upgrade here: string forms as well as numeric OIDs are fine for the object class OID. (See theolcObjectIdentifierdescription.) And heads up β object classes areSTRUCTURALby default, so if you don't say otherwise, that's the vibe you're getting. π
olcObjectClasses: ( <oid> [NAME <name>] [DESC <description>] [OBSOLETE]
[SUP <oids>] [{ ABSTRACT | STRUCTURAL | AUXILIARY }]
[MUST <oids>] [MAY <oids>] )
olcObjectIdentifierβ defines a string name that equates to a given OID. Use that string anywhere you'd use the numeric OID in objectclass and attribute definitions, easy. You can also use the name with a suffix of the form:xx, and in that case the valueoid.xxis what gets used. Cute, convenient, iconic. β¨
olcObjectIdentifier: <name> { <oid> | <name>[:<suffix>] }
π GENERAL BACKEND OPTIONS π
Okay so these entries are picky β options in them only apply to the configuration of a single type of backend. All backends may support this class of options, but currently only back-mdb does. The entry must be named olcBackend=<databasetype>,cn=config and must have the olcBackendConfig objectClass.
And <databasetype> should be one of asyncmeta, config, dnssrv, ldap, ldif, mdb, meta, monitor, null, passwd, relay, sock, or wt.
But bestie, listen: at present only back-mdb implements any options of this type, so don't you dare use this entry for any other backends. It's giving empty promises otherwise. π
π DATABASE OPTIONS π
Database options get set in entries named olcDatabase={x}<databasetype>,cn=config, and they must have the olcDatabaseConfig objectClass. Normally the config engine generates that {x} index in the RDN automatically, so you can just omit it when you're initially loading these entries. The engine's got it. π«Ά
And for the special ones, memorize this: the special frontend database is always numbered {-1} and the config database is always numbered {0}. No negotiation, that's just the law. β
π GLOBAL DATABASE OPTIONS π
okay bestie, listen up β these ones are the shared girlies β¨. You can set them in the special "frontend" database and they get inherited by all the other databases. Then any specific database can change them again with its own settings, no cap. The frontend entry has to be named olcDatabase=frontend,cn=config and it must have the olcFrontendConfig objectClass, fr fr. π«Ά
olcAccess: to <what> [ by <who> <access> <control> ]+β this is THE moment, the main character option π . It grants access (that's the<access>part) to some set of entries and/or attributes (the<what>part) by one or more requestors (the<who>part). If you don't put any access controls in at all, the default policy is "anyone and everyone can read everything, but updates are locked to rootdn" (so like,"olcAccess: to * by * read"). Go readslapd.access(5)and the "OpenLDAP Administrator's Guide" for the full tea.
Access controls you set in the frontend get appended to whatever access controls are set on the specific databases. And the rootdn of a database can always read and write EVERYTHING in that database. π
Extra extra extra special care needed on the access controls for the config database, bestie π. Unlike other databases, the default policy for the config database is to only allow access to the rootdn. Regular users should NOT get read access, and write access should be handed out very carefully to privileged administrators. Be so serious about this one.
olcDefaultSearchBase: <dn>β sets a default search base for when a client submits a non-base search request with an empty base DN. Base scoped search requests with an empty base DN? Not affected, periodt. This setting is only allowed in the frontend entry. πolcExtraAttrs: <attr>β lists what attributes need to get added to search requests. Local storage backends return the whole entire entry to the frontend, and the frontend takes care of only returning the attributes that were requested AND are allowed by ACLs. But some features, like access checking and stuff, need specific attributes that remote storage backends (proxy backends and so on) just don't automatically return π.<attr>is an attribute needed for internal purposes, so it always has to be collected, even when clients never explicitly asked for it. This attribute is multi-valued. β¨olcPasswordHash: <hash> [<hash>...]β configures one or more hashes to use when generating user passwords stored in theuserPasswordattribute during processing of LDAP Password Modify Extended Operations (RFC 3062). The<hash>has to be one of{SSHA},{SHA},{SMD5},{MD5},{CRYPT}, and{CLEARTEXT}. Default is{SSHA}. πΈ
Note that this option does not alter the normal user applications' handling of userPassword during LDAP Add, Modify, or other LDAP operations. This setting is only allowed in the frontend entry. π¦
olcReadOnly: TRUE | FALSEβ puts the database into"read-only"mode babes. Any attempt to modify it returns an"unwilling to perform"error π. By default,olcReadOnlyisFALSE. Note that when this is setTRUEon the frontend, it cannot be reset without restarting the server, because further writes to the config database will just be rejected. So likeβ¦ think before you do it β.olcRequires: <conditions>β specify a set of conditions to require (default none). This directive can be set globally and/or per-database; databases inherit global conditions, so per-database specs are additive. The conditions:bindβ requires a bind operation before directory operations.LDAPv3β requires the session to be using LDAP version 3.authcβ requires authentication before directory operations.SASLβ requires SASL authentication before directory operations.strongβ requires strong authentication before directory operations. Thestrongkeyword allows protected "simple" authentication as well as SASL authentication.noneβ can be used to require no conditions (super handy for clearing out globally set conditions inside one particular database); it must occur first in the list of conditions.
olcRestrict: <oplist>β specify a list of operations that are restricted. Restrictions on a specific database override any frontend setting. Operations can be any ofadd,bind,compare,delete,extended[=<OID>],modify,rename,search, or the special pseudo-operationsreadandwrite, which respectively summarize read and write operations. Usingrestrict writeis equivalent toolcReadOnly: TRUE(see above bestie, scroll up π ). Theextendedkeyword lets you indicate the OID of the specific operation to be restricted. UnlikeolcRestrictOp, this applies to everyone, including rootdn. π±olcRestrictOp <oplist> [control=<oid>] (by <who> <allow|reject|drop control=<oid>> [stop|continue|break])+β specify rules for 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 <em>lot</em> of its syntax and intent witholcAccessrules (slapd.access(5)). They're processed in order, and if a line matches, no further rules are considered β unless a matchingbyclause specifies abreakrule. Thedrop control=<oid>rule is notable in that it will act asrejectif the specified control is provided by the client and is marked critical; otherwise it masks that control, including from the followingolcRestrictOplines. Dropping a control might not completely avoid it having impact though β this is implementation dependent, since some control processing happens before this step π.
Operations are the same as in the olcRestrict keyword, which are tested first and apply indiscriminately.
olcSchemaDN: <dn>β specify the distinguished name for the subschema subentry that controls the entries on this server. The default is"cn=Subschema". β¨olcSecurity: <factors>β specify a set of security strength factors (separated by white space) to require β seeolcSaslSecprops'sminssfoption for a description of what security strength factors even are. This directive can be set globally and/or per-database. The factors: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.
Note that the transport factor is a measure of security provided by the underlying transport, e.g. ldapi:// (and eventually IPSEC). It is not normally used. π§
olcSizeLimit: {<integer>|unlimited}olcSizeLimit: size[.{soft|hard}]=<integer> [...]β the max number of entries to return from a search operation. The default size limit is500. Useunlimitedfor no limits at all, live your truth π. The second format lets you do a fine-grain setting of the size limits. If no special qualifiers are specified, both soft and hard limits get set. Extra args can be added in the same value. There are additional qualifiers available too β checkolcLimitsfor an explanation of all the different flags.olcSortVals: <attr> [...]β a list of multi-valued attributes whose values will always be maintained in sorted order. Using this lets Modify, Compare, and filter evaluations on these attributes run more efficiently. The resulting sort order depends on the attributes' syntax and matching rules and may not correspond to lexical order or any other recognizable order (so like, don't assume it's alphabetical bestie π ). This setting is only allowed in the frontend entry.olcTimeLimit: {<integer>|unlimited}olcTimeLimit: time[.{soft|hard}]=<integer> [...]β the max number of seconds (in real time!)slapdwill spend answering a search request. Default time limit is3600. Useunlimitedfor no limits. The second format gives you fine-grain control of the time limits. Extra args can be added in the same value. SeeolcLimitsfor an explanation of the different flags. β°
πΈ GENERAL DATABASE OPTIONS πΈ
These ones only apply to the specific database they're defined in β no sharing with the other girlies π«Ά. They're supported by every type of backend. And yes, all of the Global Database Options from up there β¬οΈ can be used here too. π
olcAddContentAcl: TRUE | FALSEβ controls whether Add operations will perform ACL checks on the content of the entry being added. This check is off by default. See theslapd.access(5)manual page for more details on ACL requirements for Add operations. πolcHidden: TRUE | FALSEβ 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 it will be ignored in checks for conflicts with other databases. By default,olcHiddenisFALSE. πolcLastMod: TRUE | FALSEβ controls whetherslapdwill automatically maintain themodifiersName,modifyTimestamp,creatorsName, andcreateTimestampattributes for entries. It also controls theentryCSNandentryUUIDattributes, which are needed by the syncrepl provider β so don't turn it off casually bestie π. By default,olcLastModisTRUE. βolcLastBind: TRUE | FALSEβ okay so this one controls whether slapd is gonna auto-maintain thepwdLastSuccessattribute on your entries, bestie. Default?FALSE, sad but true. πΈ But heads up: on a replication consumer, thepwdLastSuccessattribute gets forwarded to the provider β as long as theupdaterefsetting and thechainoverlay are both configured appropriately. iykyk πolcLastBindPrecision: <integer>β if you turned onolcLastBind, this tells you how oftenpwdLastSuccessgets updated. The rule is: more than integer seconds must have passed since the last successful bind. β±οΈ In a replicated setup with lots of bind activity, setting this to a big ol' value is lowkey useful. And on a backend, if it's set to0(which is the default, btw), then the value set on the frontend is what gets used. π«ΆolcLimits: <selector> <limit> [<limit> [...]]β okay this one is a big one, so buckle up. π This sets time and size limits based on the operation's initiator or base DN. The<selector>argument 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
So let's break it down, no cap. The DN type self is the default, and it means the bound user. Then this means the base DN of the operation. The term anonymous matches all the unauthenticated clients out there π. The term users matches all authenticated clients. Otherwise, an exact dn pattern is assumed β unless you specify otherwise by qualifying the (optional) key string dn with exact or base (which are literally synonyms, fr fr) to require an exact match; with onelevel, to require exactly one level of depth match; with subtree, to allow any level of depth match, including the exact match; with children, to allow any level of depth match but not including the exact match; and regex explicitly requires the (default) match based on POSIX (''extended'') regular expression pattern. Finally, anonymous matches unbound operations, and the pattern field just gets ignored, periodt. β¨ You get the same behavior by 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 limits that are currently supported are size and time.
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 the client didn't explicitly request a time limit, the soft limit is used. If the requested time limit exceeds the hard limit, the value of the limit is used instead. Now β if the hard limit is set to the keyword soft, then the soft limit is used in either case; and if it's set to the keyword unlimited, no hard limit is enforced at all. Explicit requests for time limits that are smaller or equal to the hard limit are honored. And if no limit specifier is set, the value is assigned to the soft limit, and the hard limit gets set to soft, just to preserve the original behavior. π¦
The syntax for size limits is size[.{soft|hard|unchecked}]=<integer>, where integer is the max number of entries slapd will return answering a search request. If the client didn't explicitly request a size limit, 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 is a whole means to drop such operations before they are 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, bestie). If it's set to disabled, the search isn't even performed β you can use this to disallow searches for a specific set of users. π And if no limit specifier is set, the value gets assigned to the soft limit, and the hard limit gets 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 olcSizeLimit and olcTimeLimit; no limit is set on unchecked.
If pagedResults control is requested, the hard size limit is used by default, because requesting a specific page size counts as an explicit request for a limitation on the number of entries to be returned. β However β careful β 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 too; 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, just so you know π). The keyword unlimited means 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 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 an unlimited number of entries to be returned β like, 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 olcLimits 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 olcSyncrepl for details). π₯
When you're using subordinate databases, it's 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 aren't honored, and that's just embarrassing. π
olcMaxDerefDepth: <depth>β specifies the maximum number of aliases to dereference when trying to resolve an entry. It's there to avoid infinite alias loops (iykyk, those are a nightmare π΅βπ«). The default is15.olcMultiProvider: TRUE | FALSEβ this one puts a consumer database into Multi-Provider mode. Update operations will be accepted from any user, not just theupdatedn. π Heads up though: the database must already be configured as asyncreplconsumer before this keyword can be set, and this mode also requires anolcServerID(see above) to be configured. By default, this setting isFALSE.olcMonitoring: TRUE | FALSEβ this enables database-specific monitoring in the entry related to the current database in the"cn=Databases,cn=Monitor"subtree of the monitor database β that is, if the monitor database is enabled. π Currently, only the MDB database provides database-specific monitoring, no cap. If monitoring is supported by the backend it defaults toTRUE, otherwiseFALSE.olcPlugin: <plugin_type> <lib_path> <init_function> [<arguments>]β configure a SLAPI plugin π. See theslapd.plugin(5)manpage for more details, bestie.olcRootDN: <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, so don't assume. An empty root DN (which is the default) means no root access is to be granted at all. It is recommended that therootdnonly be specified when needed β like when you're initially populating a database. If therootdnis within a namingContext (suffix) of the database, a simple bind password may also be provided using theolcRootPWdirective. Many optional features, includingsyncrepl, require therootdnto be defined for the database. Oh, and theolcRootDNof thecn=configdatabase defaults tocn=configitself. β¨olcRootPW: <password>β specify a password (or a hash of the password) for therootdn. π The password can only be set if therootdnis within the namingContext (suffix) of the database. This option accepts all RFC 2307userPasswordformats known to the server (see theolcPasswordHashdescription) as well as cleartext.slappasswd(8)may be used to generate a hash of a password. But real talk: cleartext and{CRYPT}passwords are not recommended, so maybe don't. π« If empty (the default), authentication of the root DN happens by other means (e.g. SASL). Use of SASL is encouraged, bestie. πolcSubordinate: [TRUE | FALSE | advertise]β ok so this one is telling slapd that the current backend database is a subordinate of another backend database, like a lil sibling database that lives inside a bigger one. Heads up: a subordinate database can have only one suffix. This is the option you use to glue multiple databases into a single namingContext β¨. If the suffix of the current database sits "within" the namingContext of a superior database, then searches against the superior get propagated down to the subordinate too. All of the databases that share a single namingContext should have identicalrootdnsbestie, don't skip that.
β οΈ Important: the behavior of other LDAP operations is unaffected by this setting. And specifically β it is not possible to use moddn to move an entry from one subordinate to another subordinate within the namingContext. No moving, no cap. π«
If you toss in 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. Shy database energy, we respect it. π
If the slap tools slapcat(8), slapadd(8), slapmodify(8), or slapindex(8) are used on the superior database, then any glued subordinates that support these tools get opened as well. Team effort π
.
Databases 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 the glued databases should be configured as similarly as possible, since the whole intent is to give the appearance of a single directory. Coordination is the vibe.
Lowkey a big one: 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 database. Its position can be explicitly configured by setting an overlay glue directive at whatever position you want. And this explicit config is actually necessary e.g. when you're using the syncprov overlay, which needs to follow glue in order to work over all the glued databases. Example time:
dn: olcDatabase={1}mdb,cn=config
olcSuffix: dc=example,dc=com
...
dn: olcOverlay={0}glue,olcDatabase={1}mdb,cn=config
...
dn: olcOverlay={1}syncprov,olcDatabase={1}mdb,cn=config
...
See the Overlays section below for more details.
olcSuffix: <dn suffix>β this is where you tell slapd which DN suffix of queries gets passed to this backend database. You can give multiplesuffixlines, and you need at least one for every database definition. Required, not optional, periodt. π
If the suffix of one database is "inside" that of another, the database with the inner suffix must come first in the configuration file. Order matters bestie!! You may also want to glue such databases together with the olcSubordinate attribute. β¨
olcSyncUseSubentry: TRUE | FALSEβ store the syncreplcontextCSNin a subentry instead of the context entry of the database. The subentry's RDN will be"cn=ldapsync". Default isFALSE, meaning thecontextCSNgets stored in the context entry like usual.olcSyncrepl:β okay sit down, get comfy, grab a snack π, because this one is the big one. Here's the whole syntax shape:
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]
So what does it do? It specifies the current database as a consumer which is kept up-to-date with the provider content by establishing 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 the deep dive on setting up a replicated slapd directory service with the syncrepl replication engine, go read the "OpenLDAP Administrator's Guide". iykyk π
rid identifies the current syncrepl directive within the replication consumer site. It's a non-negative integer not greater than 999 (limited to three decimal digits). β¨
provider specifies the replication provider site containing the provider content as an LDAP URI. If <port> is not 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 the search specification. That spec includes searchbase, scope, filter, attrs, attrsonly, sizelimit, and timelimit parameters, just like in a normal search specification. The exattrs option may also be used to specify attributes that should be omitted from incoming entries. Here are the defaults, write them down bestie:
scopedefaults tosubfilterdefaults to(objectclass=*)- there is no default
searchbase - the
attrslist defaults to"*,+"to return all user and operational attributes attrsonlyandexattrsare unset by defaultsizelimitandtimelimitonly 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 unchanged from the default otherwise replication may never succeed, fr fr. But note β 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.
The LDAP Content Synchronization protocol has two operation types:
- In the
refreshOnlyoperation, the next synchronization search operation is periodically rescheduled at an interval time (specified by theintervalparameter; 1 day by default) after each synchronization operation finishes. - In the
refreshAndPersistoperation, a synchronization search remains persistent in the providerslapd. Further updates to the provider will generatesearchResultEntryto the consumerslapdas 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 theintervalparameter; 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 the <retry interval> and <# of retries> pairs. Example: retry="60 10 300 3" lets the consumer retry every 60 seconds for the first 10 times and then retry every 300 seconds for the next 3 times before it stops retrying. The + in <# of retries> means indefinite number of retries until success. If no retry is specified, by default syncrepl retries every hour forever. Loyal to a fault π
Schema checking can be enforced at the LDAP Sync consumer site by turning on the schemachecking parameter. Default is off. Turning it on means replicated entries must have a structural objectClass, must obey objectClass requirements in terms of required/allowed attributes, and that naming attributes and distinguished values must be present. As a consequence, schemachecking should be off when partial replication is used. Got it? π
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 customizing this parameter β it's ignored otherwise and system-wide settings are used.
A bindmethod of simple requires the options binddn and credentials and should only be used when adequate security services (e.g. TLS or IPSEC) are in place.
π¨ REMEMBER: simple bind credentials must be in cleartext! Do not be casual about this one bestie, I am begging.
A bindmethod of sasl requires the option saslmech. Depending on the mechanism, an authentication identity and/or credentials can be specified using authcid and credentials. The authzid parameter may be used to specify an authorization identity. Specific security properties (as with the sasl-secprops keyword above) for a SASL bind can be set with the secprops option. A non-default SASL realm can be set with the realm option. πΈ
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, other than allowing authentication of the syncrepl identity, should grant that identity appropriate access privileges to the data being replicated (access directive), and appropriate time and size limits. This can be accomplished by either allowing unlimited sizelimit and timelimit, or by setting an appropriate limits statement in the consumer's configuration (see sizelimit and limits for details). β¨
The keepalive parameter sets the values of idle, probes, and interval used to check whether a socket is alive bestie π here's the tea: idle is the number of seconds a connection needs to remain idle before TCP starts sending keepalive probes, probes is the maximum number of keepalive probes TCP should send before dropping the connection, and interval is the interval in seconds between individual keepalive probes. Lowkey important: only some systems support the customization of these values β the keepalive parameter is ignored otherwise, and system-wide settings are used. So don't come crying to me if it does nothing, the kernel said no π
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 continues without TLS. 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 allows the consumer to pull entries from a remote directory whose DN suffix differs from the local directory. The portion of the remote entries' DNs that matches the searchbase will be replaced with the suffixmassage DN. It's giving glow-up but for DNs π
Rather than replicating whole entries, the consumer can query logs of data modifications. This mode of operation is referred to as delta syncrepl π₯ In addition to the above parameters, the logbase and logfilter parameters must be set appropriately for the log that will be used. 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 the syncdata parameter is omitted or set to "default" then the log parameters are ignored. If multiprovider is being used, the same logbase database must be configured on all of the providers. No cap π
The lazycommit parameter tells the underlying database that it can store changes without performing a full flush after each change. This may improve performance for the consumer, while sacrificing safety or durability. Bestie, that's the tradeoff β speed or safety, pick your fighter. π
olcUpdateDN: <dn>β This option is only applicable in a replica database. It specifies the DN permitted to update (subject to access controls) the replica. It is only needed in certain push-mode replication scenarios. Generally, this DN should not be the same as therootdnused at the provider. Let the provider have its own identity, okay? main character energy only where it belongs πolcUpdateRef: <url>β Specify the referral to pass back whenslapd(8)is asked to modify a replicated local database. If multiple values are specified, eachurlis provided. Cute, it collects them like stickers π
π DATABASE-SPECIFIC OPTIONS π
Each database may allow specific configuration options; they are documented separately in the backends' manual pages. See the slapd.backends(5) manual page for an overview of available backends. Basically, every backend has its own lore and you gotta read its own page for it π
π§ OVERLAYS π§
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. It's a whole stack of glow-ups stacked on top of each other π
Overlays must be configured as child entries of a specific database. The entry's RDN must be of the form olcOverlay={x}<overlaytype> and the entry must have the olcOverlayConfig objectClass. Normally the config engine generates the "{x}" index in the RDN automatically, so it can be omitted when initially loading these entries. Automation ate, honestly β¨
See the slapd.overlays(5) manual page for an overview of available overlays.
π EXAMPLES π
Here is a short example of a configuration in LDIF suitable for use with slapadd(8):
dn: cn=config
objectClass: olcGlobal
cn: config
olcPidFile: /var/lib/openldap/run/slapd.pid
olcAttributeOptions: x-hidden lang-
dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema
include: file:///etc/openldap/schema/core.ldif
dn: olcDatabase=frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: frontend
# 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).
olcAccess: to attrs=name;x-hidden by * =cs
# Protect passwords. See slapd.access(5).
olcAccess: to attrs=userPassword by * auth
# Read access to other attributes and entries.
olcAccess: to * by * read
# set a rootpw for the config database so we can bind.
# deny access to everyone else.
dn: olcDatabase=config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: config
olcRootPW: {SSHA}XKYnrjvGT3wZFQrDD5040US592LxsdLy
olcAccess: to * by * none
dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcSuffix: "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.
olcDbDirectory: /var/lib/openldap/openldap-data
# Indices to maintain
olcDbIndex: objectClass eq
olcDbIndex: cn,sn,mail pres,eq,approx,sub
# We serve small clients that do not handle referrals,
# so handle remote lookups on their behalf.
dn: olcDatabase=ldap,cn=config
objectClass: olcDatabaseConfig
objectClass: olcLdapConfig
olcDatabase: ldap
olcSuffix: ""
olcDbUri: ldap://ldap.some-server.com/
Assuming the above data was saved in a file named "config.ldif" and the /etc/openldap/slapd.d directory has been created, this command will initialize the configuration:
slapadd -F /etc/openldap/slapd.d -n 0 -l config.ldif
"OpenLDAP Administrator's Guide" contains a longer annotated example of a slapd configuration. Go read it if you want the extended cut π
Alternatively, an existing slapd.conf file can be converted to the new format using slapd or any of the slap tools:
slaptest -f /etc/openldap/slapd.conf -F /etc/openldap/slapd.d
It's giving glow-up era and honestly? Deserved πβ¨
π FILES π
/etc/openldap/slapd.confβ default slapd configuration file/etc/openldap/slapd.dβ default slapd configuration directory
π SEE ALSO π
ldap(3), ldif(5), gnutls-cli(1), slapd.access(5), slapd.backends(5), slapd.conf(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/)
The whole squad, assembled π«Ά
πΈ 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. Iconic lineage, fr fr π
aaaand that's the whole page bestie, you made it to the end!! π this was SLAPD-CONFIG(5) from OpenLDAP 2.7.2, dated 2026/10/21 β now go forth and configure your directory with main character energy, and remember: read the docs, back up your slapd.d, and hydrate π
πβ¨
π¦ where this page comes from
- arch rolling: openldap 2.7.2-2 Β· OLDAP-2.8
- Copyright 1998-2026 The OpenLDAP Foundation All Rights Reserved
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms