LLOADD.CONF(5)
π LLOADD.CONF π
okay bestie, welcome to the lloadd.conf page β that's the configuration file for lloadd, the stand-alone LDAP daemon. This lives in section 5 of the manual (File Formats Manual), so it's a file page, not a command page. Different vibe, same icon energy. π
β¨ NAME β¨
lloadd.conf β configuration file for lloadd, the stand-alone LDAP daemon π¦
πΈ SYNOPSIS πΈ
/etc/openldap/lloadd.conf
π DESCRIPTION π
So, the file /etc/openldap/lloadd.conf holds all the configuration info for the lloadd(8) daemon. It's literally where you tell the thing how to exist. π
The lloadd.conf file is a series of global configuration options that apply to lloadd as a whole β like, all of it, every backend included β and then after that, zero or more backend definitions that say how each specific backend instance should be contacted. Not one backend, not two β as many as you want, or none, no judgement. π
Key detail fr fr: the configuration options are case-insensitive, but their value, on a case-by-case basis, may be case-sensitive. So don't go lowercase-ing your values and then acting surprised. π
The general format of lloadd.conf goes like this:
# The following two lines should only be present if configured as a
# slapd module:
backend lload
listen <URIs to be managed by lloadd>
# comment - these options apply to the server as a whole
<global configuration options>
# first tier definition
tier <strategy>
# first backend definition
backend-server <backend 1 definition>
# subsequent backend/tier definitions
...
As many tiers and backend servers may be configured as desired. Go off, honestly. π₯
Now, the fiddly little syntax rules, because they will catch you slipping:
- If a line begins with white space, it counts as a continuation of the previous line. Sneaky but useful.
- No physical line should be over
2000bytes long. Like, bestie, why is your line that long. - Blank lines and comment lines beginning with a
#character are ignored. - Arguments on configuration lines are separated by white space. If an argument contains white space, wrap that argument in double quotes. If an argument contains a double quote (
") or a backslash character (\), put a backslash character in front of it. Yes, escaping. It's giving C string. π - The specific configuration options available are discussed below in the Global Configuration Options and General Backend Options. For more details on the
lloaddconfiguration file, go check the "OpenLDAP Administrator's Guide". π
β οΈ careful babe: continuation lines are unwrapped before comment processing is applied. So a # in the wrong place is not gonna save you. Keep that in mind, iykyk. π
π«Ά SLAPD INTEGRATION π«Ά
Okay this part is important, so sit up. π
When lloadd is configured as a slapd module, any option that shares the same name as an option in slapd.conf(5) β the slapd interpretation wins. Periodt. The lloadd option mentioned is unavailable through slapd.conf(5) directly; you'd have to configure it via a dedicated attribute in cn=config instead. So no, you can't just sneak it in the slapd file. π
In particular β and this is the one that gets people β unless the TLSShareSlapdCTX option is set, lloadd keeps its own TLS context, and that context cannot be configured except through the dynamic configuration. Lowkey the most important sentence on this page. π
There's an additional option available when running as a slapd module:
listen <listen URIs>β the URIs the Load Balancer module should listen on π§. It must not overlap with the ones thatslapduses for its own listening sockets β no sharing, bestie, they will fight. The relatedcn=configattribute isolcBkLloadListen, with each URI provided as a separate value. And heads up: no changes to this attribute made after the server has started up will take effect until it is restarted. So likeβ¦ restart it. It's the only way. π
β¨ GLOBAL CONFIGURATION OPTIONS β¨
okay bestie, this is the big one π
everything in here applies to all backends, no exceptions, no favourites. and quick housekeeping: any time you see angle brackets like <> in an argument, that's a placeholder β swap it for your real value, don't literally type the brackets, i'm begging you π
argsfile<filename> β the (absolute) name of a file that's gonna hold the lloadd server's command line β that's the program name and the options it was started with. receipts, basically π§Ύconcurrency<integer> β set a desired level of concurrency. this gets handed down to the underlying thread system as a hint, okay, a HINT, it's not a demand, it's giving suggestion energy β¨. the default is to not provide any hint at all.enable<feature> β switches extra LDAP Load Balancer features on. the ones you can enable are:proxyauthzβ when proxying an operation, pass along the client's authorized identity using the proxy authorization control (RFC 4370). no control gets added to the operation if it was initiated by a client whose bound identity matches the identity configured inbindconf(and btw, no normalisation of the DN is attempted here, so don't come for me about DNs). this feature is enabled by default π«Ά- and heads up: if SASL binds are issued by clients and this feature is on, your backend servers need to support the LDAP Who Am I? extended operation, otherwise the Load Balancer cannot detect the correct authorization identity. no Who Am I?, no vibe check, no authz π«
disable<feature> β the opposite slay. switches supported LDAP Load Balancer features off. same list as theenableoption, go look up there β¬οΈinclude<filename> β read extra configuration info from this file, then come right back and continue with the next line of the current file. it's a lil detour, not a takeover πΈio-threads<integer> β how many threads to use for the connection manager. default is1, and honestly that's typically adequate for up to 16 CPU cores. the value should be set to a power of 2 (yes, like 2, 4, 8, 16 β the math girlies know π§).
β οΈ if you modify this after the server has started up, the change will not take effect until the server has been restarted. periodt.
logfile<filename> β pick a file for recording lloadd debug messages. by default these messages only go tostderr, are not recorded anywhere else, and are unrelated to the messages exposed by theloglevelconfiguration parameter. also: specifying alogfilecopies messages to bothstderrand the logfile. two places, double the love π«Άlogfile-formatdebug|syslog-utc|syslog-localtimeβ sets the prefix format for messages written to the logfile.debugis the normal format used for slapd debug messages: a timestamp in hexadecimal followed by a thread ID. the other two options usesyslog(3)-style prefixes, with timestamps either in UTC or in the local timezone. the default isdebugformat.logfile-onlyon|offβ says debug messages should go only to the configured logfile and not tostderr. like, shhh, only the journal gets this tea πlogfile-rotate<max> <Mbytes> <hours> β sets up automatic rotation for the configured logfile. the three values are: the maximum number of old logfiles to retain, a maximum size in megabytes to allow a logfile to grow before rotation, and a maximum age in hours for a logfile to be used before rotation. the maximum number must be in the range1-99. settingMbytesorhoursto zero disables the size or age check respectively. at least one ofMbytesorhoursmust be non-zero. by default, no automatic rotation will be performed.loglevel<integer> [...] β specifies the level at which debugging statements and operation statistics should be syslogged (currently logged to thesyslogd(8)LOG_LOCAL4facility). important vibe: these must be considered subsystems rather than increasingly verbose log levels. some messages with higher priority are logged regardless of the configured loglevel as soon as any logging is configured. log levels are additive, and here are the available ones: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 received64(0x40config) β configuration file processing256(0x100stats) β connections, LDAP operations, results (recommended π)512(0x200stats2) β stats log entries sent32768(0x8000none) β only messages that get logged whatever log level is set
the desired log level can be input as a single integer that combines the (ORed) desired levels β in decimal or hexadecimal notation β as a list of integers (that are ORed internally), or as a list of the names shown between the parentheses. so like, all of these are equivalent, no cap:
loglevel 513
loglevel 0x201
loglevel 512 1
loglevel 0x200 0x1
loglevel stats trace
the keyword any can be used as a shortcut to enable logging at all levels (equivalent to -1). the keyword none, or the equivalent integer representation, causes those messages that are logged regardless of the configured loglevel to be logged. and in fact β if loglevel is set to 0, no logging occurs, so at least the none level is required to have high priority messages logged. don't set it to zero and then be confused, that's a you problem bestie π
the loglevel defaults to stats. this level should usually also be included when using other loglevels, to help analyze the logs. literally just leave stats in there.
pidfile<filename> β the (absolute) name of a file that will hold the lloadd server's process ID (seegetpid(2)). it's the server's lil name tag πsockbuf_max_incoming_client<integer> β the maximum LDAP PDU size accepted coming from clients. the default is262143.sockbuf_max_incoming_upstream<integer> β the maximum LDAP PDU size accepted coming from upstream connections. the default is4194303.sockbuf_max_pending_client<integer> β the maximum amount of data we can store toward a client connection. the default is0, which means no limit on the data being buffered. zero = yolo πtcp-buffer[listener=<URL>] [{read|write}=]<size>β sets the size of the TCP buffer. a global value for both read and write TCP buffers related to any listener is defined, unless the listener is explicitly specified, or either thereadorwritequalifiers are used. seetcp(7)for details. also note that some OS-es implement automatic TCP buffer tuning, so your OS might be doing its own thing β¨threads<integer> β the maximum size of the primary thread pool. the default is16; the minimum value is2.threadqueues<integer> β the number of work queues to use for the primary thread pool. the default is1and this is typically adequate for up to 8 CPU cores. the value should not exceed the number of CPUs in the system β don't be greedy πmax_pdus_per_cycle<integer> β if set to0, PDUs are handled by the I/O threads directly. otherwise a task is queued to be picked up by the thread pool; this task will process PDUs from the connection until there is no more data to be read or this limit is reached, at which point the I/O thread can pick it up again. very high values have the potential to cause some connections to be starved in a very high-bandwidth environment π¬. the default is1000.client_max_pending<integer> β makes the load balancer limit the number of unfinished operations for each client connection. the default is0, unlimited.iotimeout<integer> β the number of milliseconds to wait before forcibly closing a connection with an outstanding write. this allows faster recovery from various network hang conditions (goodbye limbo π). aniotimeoutof0disables this feature. the default is10000.write_coherence<integer> β the number of seconds after a write operation is finished that lloadd will direct operations exclusively to the last selected backend. a write operation is anything not handled internally (certain exops, abandon), except search, compare and bind operations. bind operations also reset this restriction. the default is0, meaning write operations do not restrict selection. when negative, the restriction is not time limited and will persist until the next bind.restrict_exop<OID> <action> β tells lloadd that an extended operation with a given OID should be handled in a specific way. OID1.1is special: it sets a default, and that's only for operations not handled internally. the meaning of the <action> argument is the same as inrestrict_controlbelow β¬οΈrestrict_control<OID> <action> β tells lloadd that a control with a given OID attached to any operation should be handled in a specific way according to the <action> argument. at the moment, only operations passed intact are inspected in this way β in particular, controls on bind and extended operations are not checked, so don't expect those to get the treatment π«
in order of descending priority (the control with the highest priority action wins), these are the actions:
rejectβ operations that carry this control will be rejected. absolutely not, blocked, declined π€connectionβ once an upstream is selected, every future operation from this client will be directed to the same connection. super useful when state is shared between client and upstream that the load balancer doesn't track.backendβ likewrite, except this does not time out.writeβ this is treated like a write operation (seewrite_coherenceabove β¬οΈ).ignoreβ does not influence restrictions. useful when you're changing the global exop default. this is the default handling for exops/controls not handled by the load balancer internally.
β¨ TLS OPTIONS β¨
So if lloadd was built with Transport Layer Security support (bestie, it should be, TLS is the vibe), you get a whole extra menu of options to play with. πΈ
TLSShareSlapdCTX { on | off }β okay so if you set this tono(which is the default, no cap),lloaddis gonna roll with its own TLS context. Heads up though: you have to configure that yourself viacn=config, unlesslloaddis running as a standalone daemon. If you flip itoninstead, then theslapdoptions apply instead, because bestie we're literally borrowing slapd's TLS context. Sharing is caring. π«Ά
The following options are available only when compiled as a standalone daemon. If you're running it compiled as a slapd(8) module, you need to use the cn=config equivalents if the module needs its own separate TLS context β otherwise, just use the TLSShareSlapdCTX option up there and call it a day. π
TLSCipherSuite <cipher-suite-spec>β lets you configure which ciphers get accepted and in what preference order. The<cipher-suite-spec>should be a cipher specification for whatever TLS library you're using (OpenSSL or GnuTLS). This directive is not supported when using MbedTLS. Example time:
OpenSSL:
TLSCipherSuite HIGH:MEDIUM:+SSLv2
GnuTLS:
TLSCiphersuite 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) (peep the description of the --priority option). And 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>β points to the file holding certificates for all the Certificate Authoritieslloaddis gonna recognize. The cert for the CA that signed the server certificate must be in there. And if that signing CA wasn't a top-level (root) CA? Then you want certs for the entire sequence of CA's from the signing CA all the way up to the top-level CA present in the file. Multiple certificates just get appended to the file, and the order doesn't matter β no stress. β¨TLSCACertificatePath <path>β the path of a directory that holds Certificate Authority certificates in separate individual files. Usually you only use this one or theTLSCACertificateFile, not both. Not supported when using GnuTLS.TLSCertificateFile <filename>β the file with thelloaddserver certificate in it. That's it, that's the one. πTLSCertificateKeyFile <filename>β the file with thelloaddserver private key that matches the certificate sitting in theTLSCertificateFile. Currently, the private key must not be protected with a password β which means it is of critical importance that you protect it carefully. Like, lock it down, bestie. This is not the time to be casual. πTLSDHParamFile <filename>β specifies the file with parameters for Diffie-Hellman ephemeral key exchange. You need this to use a DSA certificate on the server, or an RSA certificate that's 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, and Anonymous key exchanges should generally be avoided since they provide no actual client or server authentication and zero protection against man-in-the-middle attacks. You should append"!ADH"to your cipher suites to make sure those suites don't get used. Not supported when using MbedTLS.TLSECName <name>β specify the name of a curve to use for Elliptic curve Diffie-Hellman ephemeral key exchange. This is required to enable ECDHE algorithms in OpenSSL. This option is not used with GnuTLS β over there the curves get chosen in the GnuTLS ciphersuite specification instead. π¦TLSProtocolMin <major>[.<minor>]β sets the minimum SSL/TLS protocol version that'll be negotiated. If the server doesn't support at least that version, the SSL handshake fails, periodt. To require TLS 1.x or higher, set this option to3.(x+1), like:
TLSProtocolMin 3.2
which would require TLS 1.1. If you specify a minimum higher than what the OpenLDAP implementation supports, it'll just end up requiring the highest level that it does support. This directive is ignored with GnuTLS.
TLSRandFile <filename>β the file to grab random bits from when/dev/[u]randomisn't available. Generally you'd set this to the name of the EGD/PRNGD socket. The environment variableRANDFILEcan also be used to specify the filename. Ignored with GnuTLS.TLSVerifyClient <level>β specifies what checks to perform on client certificates in an incoming TLS session, if any. The<level>can be one of these keywords:neverβ this is the default.lloaddwill 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, kept around for compatibility reasons. The client certificate is requested. If no certificate is provided, or a bad certificate is provided, the session is immediately terminated.
TLSCRLCheck <level>β specifies if the Certificate Revocation List (CRL) of the CA should be used to verify that client certificates haven't been revoked. This requires theTLSCACertificatePathparameter to be set. This directive is ignored with GnuTLS. The<level>can be 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
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.
π BACKEND CONFIGURATION π
The options in this section are all about how lloadd connects and authenticates to the backend servers. And here's the tea: backends are organised into groups β we call them tiers. π
Backends in the first tier get tried first. If none of them are reachable, the next tier gets tried the same way. But here's the plot twist: if there's a backend in the tier that has suitable connections but they're all busy, no further tier is consulted. This is super useful in high availability scenarios where a group of servers (like your local environment, say) should be contacted if possible. β¨
It's assumed that all backend servers serve the same data. On startup, the configured connections get set up, and those not dedicated to handling bind requests are authenticated with the backend using the info in the bindconf option. That authentication configuration is shared between all of them. π«Ά
bindconf
[bindmethod=simple|sasl] [binddn=<dn>] [saslmech=<mech>]
[authcid=<identity>] [authzid=<identity>] [credentials=<passwd>]
[realm=<realm>] [secprops=<properties>] [timeout=<seconds>]
[network-timeout=<seconds>]
[keepalive=<idle>:<probes>:<interval>]
[tcp-user-timeout=<milliseconds>] [tls_cert=<file>]
[tls_key=<file>] [tls_cacert=<file>] [tls_cacertdir=<path>]
[tls_reqcert=never|allow|try|demand] [tls_cipher_suite=<ciphers>]
[tls_crlcheck=none|peer|all] [tls_protocol_min=<major>[.<minor>]]
Specifies the bind credentials lloadd uses when it's setting up its regular connections to all the backends. π
A bindmethod of simple requires the binddn and credentials options, and you should only use it when adequate security services (like TLS or IPSEC) are in place. REMEMBER: simple bind credentials must be in cleartext! π A bindmethod of sasl requires the saslmech option. 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 (same vibe as the sasl-secprops keyword above) for a SASL bind can be set with the secprops option. And a non-default SASL realm can be set with the realm option.
The timeout parameter says how long an operation can be pending a response (result, search entry, ...) from the server, in seconds. And because of how timeouts are detected, ngl the timeout might not get detected and handled until up to timeout seconds after it actually happens. π
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.
Timeout set to 0 means no timeout is in effect, and by default, no timeouts are in effect. π¦
The keepalive parameter sets the values of idle, probes, and interval used to check whether a socket is alive. So: 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; interval is the interval in seconds between individual keepalive probes. Only some systems support customizing these values β otherwise the keepalive parameter is ignored and system-wide settings are used.
The tcp-user-timeout parameter, if non-zero, corresponds to the TCP_USER_TIMEOUT set on the upstream connections, overriding the operating system setting. Again, only some systems support the customization of this parameter β otherwise it's ignored and system-wide settings are used. π
β¨ TIER OPTIONS β¨
tier <tier type>β this is how you group servers that should all be considered in the same try π«Ά. Like, they're on the same team. If a viable connection gets found β even if it's busy β the load balancer does not move on to the next tier. Periodt. And how a connection gets picked inside a tier? Depends on that tier's type, bestie.
The types you can use are:
roundrobinβ servers get tried in order, and if one of them is selected successfully, the next search starts from the one right after it on the list. Very "take turns, no favorites" energy πweightedβ backend servers accept a new optionweight=<int>which says how often that server should be picked. If you don't specify it,weightdefaults to0, and those backends have a slight chance of being selected even when a non-zero weight backend exists in the tier π. The selection process is along the lines ofRFC2782.bestofβ just likeweighted, backends accept theweight=<int>option. Average latency multiplied by weight gets measured over time. Then the selection picks 2 backends at random, compares their weighted latencies, and the backend with a better (lower) score gets tried. If that backend isn't available (or it's busy π), the other backend gets tried, and after that backends are chosen in a round-robin order.
Heads up bestie: unlike weighted, the higher the weight, the higher the "effective" latency and the lower the chance a backend is selected. It's giving opposite day π
β¨ BACKEND OPTIONS β¨
backend-serverβ
uri=ldap[s]://<hostname>[:port] [retry=<retry interval in ms>]
[starttls=yes|critical] [numconns=<conns>] [bindconns=<conns>]
[max-pending-ops=<ops>] [conn-max-pending=<ops>]
This marks the beginning of a backend definition π
uri specifies the backend as an LDAP URI. If <port> isn't given, the standard LDAP port number (389 or 636) is used.
Lloadd will attempt to maintain numconns active connections, plus bindconns active connections dedicated to handling client bind requests.
If an error happens on a working connection, a new connection attempt gets made immediately. But if it happens while establishing a new connection to this backend, lloadd will wait before making a new reconnect attempt, according to the retry parameter β default is 5 seconds β³
Operations get distributed across the backend's connections (upstreams).
The parameter conn-max-pending, unless it's set to 0 (the default), will limit the number of unfinished operations per upstream connection. Similarly, max-pending-ops limits the total number of unfinished operations across all of the backend's connections. 0, the default, means no limit gets imposed for this backend. Slay, no caps π§’
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" and the other TLS settings default to the same as the main slapd TLS settings. π
π EXAMPLES π
Here's a short example of a configuration file, bestie β she's beautiful:
argsfile /var/lib/openldap/run/lloadd.args
pidfile /var/lib/openldap/run/lloadd.pid
# cancel not supported yet
restrict_exop 1.3.6.1.1.8 reject
# turn not supported
restrict_exop 1.3.6.1.1.19 reject
# TXN Exop if desired, otherwise reject
restrict_exop 1.3.6.1.1.21.1 connection
# Paged results control
restrict_control 1.2.840.113556.1.4.319 connection
# VLV control
restrict_control 2.16.840.1.113730.3.4.9 connection
bindconf
bindmethod=simple
binddn=cn=test
credentials=pass
tier weighted
backend-server
uri=ldap://ldap1.example.com
numconns=3
bindconns=2
retry=5000
max-pending-ops=5
conn-max-pending=3
weight=5
backend-server
uri=ldap://ldap2.example.com
numconns=3
bindconns=2
retry=5000
max-pending-ops=5
conn-max-pending=3
weight=10
"OpenLDAP Administrator's Guide" contains a longer annotated example of a configuration file. And the original /etc/openldap/lloadd.conf is another example π
π LIMITATIONS π
Support for proxying SASL Binds is limited to the EXTERNAL mechanism (and only to extract the DN of a client TLS certificate if it was used during the last renegotiation) and mechanisms that rely neither on connection metadata (the way Kerberos does) nor establish a SASL integrity/confidentiality layer (again, some Kerberos mechanisms β DIGEST-MD5 can negotiate this). So yeah, that's the vibe check she didn't pass π
π FILES π
/etc/openldap/lloadd.confβ the default lloadd configuration file π
π₯ SEE ALSO π₯
ldap(3), gnutls-cli(1), slapd.conf(5), tcp(7), lloadd(8), slapd(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 a wrap on this whole page, bestie!! πβ¨ This is OpenLDAP 2.7.2, dated 2026/10/21, and it lives at LLOADD.CONF(5) β go configure something iconic, you absolute main character π π¦
π¦ 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