How To Install OpenLDAP on AlmaLinux 10

Install OpenLDAP on AlmaLinux 10

Managing user authentication across multiple Linux servers without a centralized directory is a recipe for administrative chaos. When you need one source of truth for user accounts, groups, and access policies, OpenLDAP is the go-to open-source solution that sysadmins have trusted for decades. This guide walks you through a complete OpenLDAP on AlmaLinux 10 setup, from installing build dependencies to enabling TLS encryption and verifying the installation. By the end, you will have a production-ready directory server running OpenLDAP 2.6.13 on AlmaLinux 10.

One important thing to know upfront: AlmaLinux 10, like its upstream RHEL 10, no longer ships the openldap-servers RPM package in its repositories. That means the standard dnf install openldap-servers command you may have used on older RHEL systems will not work here. Instead, you need to compile OpenLDAP directly from source. This guide covers that entire process in detail so you know exactly what you are doing and why at every step.

What Is OpenLDAP and Why Does It Matter for AlmaLinux 10?

OpenLDAP is an open-source implementation of the Lightweight Directory Access Protocol (LDAP). It stores users, groups, and organizational data in a hierarchical directory tree, similar in concept to Microsoft Active Directory but built natively for Linux and Unix environments.

Here are the most common real-world use cases for running OpenLDAP on a Linux server:

  • Centralized user authentication across multiple Linux servers without managing separate /etc/passwd entries on each machine
  • Single Sign-On (SSO) foundation for web applications, VPNs, and mail servers
  • POSIX account management for granting SSH login access based on group membership
  • Integration with SSSD for seamless Linux client authentication

AlmaLinux 10 uses the RHEL 10 codebase, which dropped the openldap-servers package. This means you must build OpenLDAP from source. The current stable release is OpenLDAP 2.6.13, which uses the MDB (Memory-Mapped Database) backend. MDB replaces the old BDB and HDB backends, offering better performance and reliability.

Prerequisites

Before you start this Linux server tutorial, make sure the following are in place:

  • A server running AlmaLinux 10 with at least 2 GB of RAM and 20 GB of disk space
  • Root or sudo access to the server
  • A fully qualified domain name (FQDN) configured on the server (set it with hostnamectl set-hostname ldap.example.com)
  • Ports 389 (LDAP) and 636 (LDAPS) available and not blocked
  • Active internet access to download the OpenLDAP source tarball
  • Basic familiarity with the Linux terminal and text editors such as vim or nano

Confirm your OS version before starting:

cat /etc/almalinux-release

Expected output:

AlmaLinux release 10.0 (Purple Lion)

Step 1: Update AlmaLinux 10

Always start with a full system update. This prevents dependency conflicts and ensures all security patches are in place before you build new software.

sudo dnf update -y

If the update includes a new kernel or core library changes, reboot before continuing:

sudo reboot

After the reboot, verify your OS version one more time to confirm you are working on the right machine.

Step 2: Install Required Build Dependencies

Because the OpenLDAP server daemon (slapd) is not available as a pre-built package on AlmaLinux 10, you need a full compiler toolchain and several development libraries to build it from source.

First, install the Development Tools group, which includes gcc, make, autoconf, and related utilities:

sudo dnf groupinstall "Development Tools" -y

Next, install the specific development libraries that OpenLDAP needs at compile time:

sudo dnf install wget vim cyrus-sasl-devel libtool-ltdl-devel \
openssl-devel make libtool autoconf tar gcc perl perl-devel groff -y

Here is what the key packages do:

  • cyrus-sasl-devel: Enables SASL authentication support in OpenLDAP
  • openssl-devel: Required for TLS/SSL encryption at compile time
  • libtool-ltdl-devel: Needed for dynamic module loading support
  • groff: Required for man page generation during the build

Verify the compiler installed correctly:

gcc --version

You should see output similar to gcc (GCC) 14.x.x.

Step 3: Create the LDAP System User Account

Running slapd as a dedicated non-privileged system user is a security best practice. If the service is ever compromised, the attacker is limited to that user’s permissions rather than root access.

Create the system user with a fixed UID of 55, no home directory, and no login shell:

sudo useradd -r -M -d /var/lib/openldap -u 55 -s /usr/sbin/nologin ldap

Verify the user was created successfully:

id ldap

Expected output:

uid=55(ldap) gid=55(ldap) groups=55(ldap)

The -M flag skips home directory creation. The data directory /var/lib/openldap will be set up manually in a later step with proper ownership.

Step 4: Download and Extract the OpenLDAP Source Code

Download the latest stable OpenLDAP tarball directly from the official release page. Using a version variable makes the commands reusable when newer versions are released.

VER=2.6.13
wget https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-${VER}.tgz

Extract the archive and move it to /opt to keep your source builds organized and separate from system files:

tar xzf openldap-${VER}.tgz
sudo mv openldap-${VER} /opt/openldap-${VER}

Confirm the directory is in place:

ls /opt/openldap-${VER}

You should see the source tree directories including servers/, clients/, libraries/, and the configure script.

Step 5: Compile and Install OpenLDAP from Source

Navigate into the source directory and run the configure script. The flags you pass here determine which features get compiled into the binary.

cd /opt/openldap-${VER}

Run the configure script with TLS, SASL, and module support enabled:

sudo ./configure --prefix=/usr --sysconfdir=/etc \
  --enable-debug --with-tls=openssl --with-cyrus-sasl \
  --enable-dynamic --enable-crypt --enable-spasswd \
  --enable-slapd --enable-modules --enable-rlookups

Here is what the important flags mean:

  • --with-tls=openssl: Uses OpenSSL for encryption instead of GnuTLS
  • --with-cyrus-sasl: Enables SASL authentication mechanisms
  • --enable-modules: Allows loading modules like back_mdb.la at runtime
  • --enable-slapd: Explicitly includes the server daemon in the build

A successful configure run ends with: “Please run make depend to build dependencies”. Now build and install:

sudo make depend
sudo make
sudo make install

The make step takes a few minutes depending on your server’s CPU speed. After it completes, verify the installation:

/usr/libexec/slapd -VV

Expected output:

@(#) $OpenLDAP: slapd 2.6.13 (Mar 21 2026)

Confirm the configuration files are in place:

ls /etc/openldap/

You should see certs/, schema/, ldap.conf, slapd.conf, and slapd.ldif.

Step 6: Configure OpenLDAP with cn=config Backend

This is the most technical section of the guide. cn=config is OpenLDAP’s dynamic configuration backend, stored under /etc/openldap/slapd.d/. Unlike the older static slapd.conf approach, cn=config lets you apply configuration changes via standard LDAP operations while the server is running, without a restart.

Start by creating the required directories and setting ownership:

sudo mkdir -p /var/lib/openldap /etc/openldap/slapd.d
sudo chown -R ldap:ldap /var/lib/openldap
sudo chown root:ldap /etc/openldap/slapd.conf
sudo chmod 640 /etc/openldap/slapd.conf

Create the Sudo Schema LDIF

The sudo schema allows you to manage sudoers rules through LDAP rather than editing /etc/sudoers on every server. First, check that your system’s sudo binary supports LDAP:

sudo -V | grep -i ldap

Locate the schema file that ships with the sudo package:

rpm -ql sudo | grep schema.OpenLDAP

Copy it to the OpenLDAP schema directory:

sudo cp /usr/share/doc/sudo/schema.OpenLDAP /etc/openldap/schema/sudo.schema

Now create the LDIF version of the sudo schema at /etc/openldap/schema/sudo.ldif:

sudo vi /etc/openldap/schema/sudo.ldif

Add the following content:

dn: cn=sudo,cn=schema,cn=config
objectClass: olcSchemaConfig
cn: sudo
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.1 NAME 'sudoUser'
  DESC 'User(s) who may run sudo' EQUALITY caseExactIA5Match
  SUBSTR caseExactIA5SubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost'
  DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match
  SUBSTR caseExactIA5SubstringsMatch
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.3 NAME 'sudoCommand'
  DESC 'Command(s) to be executed by sudo' EQUALITY caseExactIA5Match
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.5 NAME 'sudoOption'
  DESC 'Options(s) followed by sudo' EQUALITY caseExactIA5Match
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.6 NAME 'sudoRunAsUser'
  DESC 'User(s) impersonated by sudo' EQUALITY caseExactIA5Match
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcAttributeTypes: ( 1.3.6.1.4.1.15953.9.1.7 NAME 'sudoRunAsGroup'
  DESC 'Group(s) impersonated by sudo' EQUALITY caseExactIA5Match
  SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
olcObjectClasses: ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top
  STRUCTURAL DESC 'Sudoer Entries' MUST ( cn )
  MAY ( sudoUser $ sudoHost $ sudoCommand $ sudoRunAsUser $
        sudoRunAsGroup $ sudoOption $ description ) )

Configure the slapd.ldif Database File

Back up the default slapd.ldif before replacing it:

sudo mv /etc/openldap/slapd.ldif /etc/openldap/slapd.ldif.bak

Create a fresh slapd.ldif with the global config, MDB backend module, required schemas, and database access controls:

sudo vi /etc/openldap/slapd.ldif

Add the following:

dn: cn=config
objectClass: olcGlobal
cn: config
olcArgsFile: /var/lib/openldap/slapd.args
olcPidFile: /var/lib/openldap/slapd.pid

dn: cn=schema,cn=config
objectClass: olcSchemaConfig
cn: schema

dn: cn=module,cn=config
objectClass: olcModuleList
cn: module
olcModulepath: /usr/libexec/openldap
olcModuleload: back_mdb.la

include: file:///etc/openldap/schema/core.ldif
include: file:///etc/openldap/schema/cosine.ldif
include: file:///etc/openldap/schema/nis.ldif
include: file:///etc/openldap/schema/inetorgperson.ldif
include: file:///etc/openldap/schema/sudo.ldif

dn: olcDatabase=frontend,cn=config
objectClass: olcDatabaseConfig
objectClass: olcFrontendConfig
olcDatabase: frontend
olcAccess: to dn.base="cn=Subschema" by * read
olcAccess: to *
  by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
  by * none

dn: olcDatabase=config,cn=config
objectClass: olcDatabaseConfig
olcDatabase: config
olcRootDN: cn=config
olcAccess: to *
  by dn.base="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
  by * none

Run a dry run first to catch any typos or missing schema references before applying:

sudo slapadd -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif -u

If the dry run completes cleanly with Closing DB... and no errors, apply the configuration:

sudo slapadd -n 0 -F /etc/openldap/slapd.d -l /etc/openldap/slapd.ldif

Set ownership on the configuration directory:

sudo chown -R ldap:ldap /etc/openldap/slapd.d

Step 7: Create the systemd Service File and Start slapd

Since you installed OpenLDAP from source, there is no systemd unit file included. You need to create one manually at /etc/systemd/system/slapd.service.

sudo vi /etc/systemd/system/slapd.service

Add the following service definition:

[Unit]
Description=OpenLDAP Server Daemon
After=syslog.target network-online.target
Documentation=man:slapd
Documentation=man:slapd-mdb

[Service]
Type=forking
PIDFile=/var/lib/openldap/slapd.pid
Environment="SLAPD_URLS=ldap:/// ldapi:/// ldaps:///"
Environment="SLAPD_OPTIONS=-F /etc/openldap/slapd.d"
ExecStart=/usr/libexec/slapd -u ldap -g ldap -h ${SLAPD_URLS} $SLAPD_OPTIONS

[Install]
WantedBy=multi-user.target

Reload systemd and enable the service to start at boot:

sudo systemctl daemon-reload
sudo systemctl enable --now slapd

Verify slapd is running:

systemctl status slapd

You should see Active: active (running) in the output. If you see failed, check the journal immediately with sudo journalctl -u slapd -xe to review the error.

Step 8: Configure the Root DN and MDB Database Backend

With slapd running, you can now configure the MDB database backend that will hold your actual directory data. Start by generating a hashed password for the root DN (your LDAP administrator account):

sudo slappasswd

You will be prompted twice. Copy the output hash that starts with {SSHA}.

Create the root DN LDIF file:

vi rootdn.ldif

Add the following content. Replace dc=example,dc=com with your actual domain and paste your {SSHA} hash at olcRootPW:

dn: olcDatabase=mdb,cn=config
objectClass: olcDatabaseConfig
objectClass: olcMdbConfig
olcDatabase: mdb
olcDbMaxSize: 42949672960
olcDbDirectory: /var/lib/openldap
olcSuffix: dc=example,dc=com
olcRootDN: cn=admin,dc=example,dc=com
olcRootPW: {SSHA}YourHashedPasswordHere
olcDbIndex: uid pres,eq
olcDbIndex: cn,sn pres,eq,approx,sub
olcDbIndex: mail pres,eq,sub
olcDbIndex: objectClass pres,eq
olcDbIndex: loginShell pres,eq
olcDbIndex: sudoUser,sudoHost pres,eq
olcAccess: to attrs=userPassword,shadowLastChange,shadowExpire
  by self write
  by anonymous auth
  by dn.subtree="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
  by dn.subtree="ou=system,dc=example,dc=com" read
  by * none
olcAccess: to dn.subtree="ou=system,dc=example,dc=com"
  by dn.subtree="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
  by * none
olcAccess: to dn.subtree="dc=example,dc=com"
  by dn.subtree="gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth" manage
  by users read
  by * none

Apply the configuration to the running slapd instance:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f rootdn.ldif

Expected output:

SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
adding new entry "olcDatabase=mdb,cn=config"

Step 9: Add the Base DN and Organizational Units

Now define the top of your directory tree with a base domain object and two organizational units (OUs): one for user accounts and one for groups.

vi basedn.ldif

Add the following, replacing the domain components with your own:

dn: dc=example,dc=com
objectClass: dcObject
objectClass: organization
objectClass: top
o: Example Organization
dc: example

dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
objectClass: top
ou: groups

dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
objectClass: top
ou: people

Import the base DN:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f basedn.ldif

You should see three adding new entry lines, one for each object.

Step 10: Create LDAP Users and a Bind DN Service Account

With the directory structure in place, add your first user. A standard LDAP user entry needs the inetOrgPerson, posixAccount, and shadowAccount objectClasses to support both directory lookups and Linux login.

vi users.ldif
dn: uid=jdoe,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: jdoe
cn: John
sn: Doe
loginShell: /bin/bash
uidNumber: 10000
gidNumber: 10000
homeDirectory: /home/jdoe
shadowMax: 60
shadowMin: 1
shadowWarning: 7
shadowInactive: 7
shadowLastChange: 0

dn: cn=jdoe,ou=groups,dc=example,dc=com
objectClass: posixGroup
cn: jdoe
gidNumber: 10000
memberUid: jdoe

Import the user:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f users.ldif

Set the user’s password:

sudo ldappasswd -H ldapi:/// -Y EXTERNAL -S "uid=jdoe,ou=people,dc=example,dc=com"

Create a Read-Only Bind DN Service Account

A bind DN is a service account that LDAP clients use to authenticate against the directory for read-only lookups, such as resolving user IDs and group memberships. Using a dedicated bind DN keeps your admin credentials out of every client’s configuration file.

Generate a separate password hash for the bind DN:

sudo slappasswd

Create the bind DN LDIF:

vi bindDNuser.ldif
dn: ou=system,dc=example,dc=com
objectClass: organizationalUnit
objectClass: top
ou: system

dn: cn=readonly,ou=system,dc=example,dc=com
objectClass: organizationalRole
objectClass: simpleSecurityObject
cn: readonly
userPassword: {SSHA}YourBindDNPasswordHash
description: Bind DN user for LDAP client operations

Apply the bind DN:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f bindDNuser.ldif

Step 11: Enable TLS/SSL Encryption for OpenLDAP

Without TLS, credentials travel between clients and the LDAP server in plain text. Port 389 without encryption is acceptable on a private loopback interface only. For any network traffic, TLS is required.

There are two approaches:

  • LDAPS (port 636): Full TLS from the moment a connection opens
  • StartTLS: Upgrades a plain port 389 connection to TLS before sending credentials

For production, use a CA-signed certificate from Let’s Encrypt or your internal PKI. This guide uses a self-signed certificate.

Generate the certificate and private key:

sudo openssl req -x509 -nodes -days 365 \
  -newkey rsa:2048 \
  -keyout /etc/pki/tls/ldapserver.key \
  -out /etc/pki/tls/ldapserver.crt

Set proper ownership so the ldap user can read both files:

sudo chown ldap:ldap /etc/pki/tls/{ldapserver.crt,ldapserver.key}

Create the TLS configuration LDIF:

sudo vi add-tls.ldif
dn: cn=config
changetype: modify
add: olcTLSCACertificateFile
olcTLSCACertificateFile: /etc/pki/tls/ldapserver.crt
-
add: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/pki/tls/ldapserver.key
-
add: olcTLSCertificateFile
olcTLSCertificateFile: /etc/pki/tls/ldapserver.crt

Apply it:

sudo ldapadd -Y EXTERNAL -H ldapi:/// -f add-tls.ldif

Update the LDAP client config to trust the certificate:

sudo vi /etc/openldap/ldap.conf

Change the TLS_CACERT line to:

TLS_CACERT /etc/pki/tls/ldapserver.crt

Restart slapd and verify both ports are open:

sudo systemctl restart slapd
ss -tlnp | grep slapd

Expected output shows listeners on both port 389 and port 636.

Step 12: Open Firewall Ports for LDAP and LDAPS

AlmaLinux 10 uses firewalld as its default firewall manager. Open both LDAP and LDAPS services permanently:

sudo firewall-cmd --add-service={ldap,ldaps} --permanent
sudo firewall-cmd --reload

Verify both services are active:

sudo firewall-cmd --list-services

Expected output includes ldap ldaps alongside any existing services like ssh and cockpit.

Port Protocol Purpose
389 TCP LDAP (plain or StartTLS)
636 TCP LDAPS (TLS from connection start)

Step 13: Test the OpenLDAP Installation with ldapsearch

Run three progressive tests to confirm everything works end to end.

Test 1: Local EXTERNAL SASL query (verifies slapd responds and base DN is visible):

sudo ldapsearch -H ldapi:/// -Y EXTERNAL -b "dc=example,dc=com" -LLL

You should see output listing dc=example,dc=com, the two OUs, and the jdoe user entry.

Test 2: Bind DN authentication over plain LDAP (verifies client-style authentication works):

ldapsearch -x -H ldap://127.0.0.1 \
  -D "cn=readonly,ou=system,dc=example,dc=com" \
  -W -b "ou=people,dc=example,dc=com"

Enter the bind DN password when prompted. A successful response returns the user entries.

Test 3: LDAPS encrypted connection (verifies TLS on port 636 is operational):

ldapsearch -x -H ldaps://127.0.0.1 \
  -D "cn=readonly,ou=system,dc=example,dc=com" \
  -W -b "ou=people,dc=example,dc=com"

You can also confirm individual user authentication with:

ldapwhoami -x -D "uid=jdoe,ou=people,dc=example,dc=com" -W

Troubleshooting Common OpenLDAP Issues on AlmaLinux 10

Even with a clean install, a few issues come up regularly across the community. Here are the most common ones with direct solutions.

Problem: ldap_add: Insufficient access (50) when applying rootdn.ldif

  • Cause: The olcAccess rules in slapd.ldif are too restrictive or the config database ACL was not applied correctly.
  • Fix: Verify the current ACLs on the config database:
sudo ldapsearch -Y EXTERNAL -H ldapi:/// -b "cn=config" "(olcDatabase=config)" olcAccess

Ensure the EXTERNAL SASL DN has manage access. If not, re-apply slapd.ldif with the correct ACL block.

Problem: include file:///etc/openldap/schema/ppolicy.ldif failed

  • Cause: The ppolicy schema was referenced in slapd.ldif but the file does not exist.
  • Fix: Remove the ppolicy include line from slapd.ldif if you do not need password policy features. If you do need it, create the ppolicy.ldif from the schema source in /etc/openldap/schema/ppolicy.schema before running slapadd.

Problem: index attribute "sudoUser" undefined

  • Cause: The rootdn.ldif references sudoUser in olcDbIndex but the sudo schema was not loaded into cn=config yet.
  • Fix: Confirm sudo.ldif is included in slapd.ldif before the olcDatabase=mdb entry. Delete /etc/openldap/slapd.d, re-run slapadd with the corrected slapd.ldif, then re-apply rootdn.ldif.

Problem: chown: invalid user: 'ldap:ldap'

  • Cause: The ldap system user was not created before running chown commands.
  • Fix: Run the useradd command from Step 3 first, then retry the chown commands.

Problem: slapd starts but LDAPS on port 636 refuses connections

  • Fix: Verify TLS is configured correctly using:
openssl s_client -connect localhost:636 -showcerts

If you see a certificate error, recheck the file paths and ownership in add-tls.ldif. Also confirm the SLAPD_URLS environment variable in the systemd service file includes ldaps:///.

Congratulations! You have successfully installed OpenLDAP. Thanks for using this tutorial for installing OpenLDAP on your AlmaLinux OS 10 system. For additional or useful information, we recommend you check the official OpenLDAP website.

VPS Manage Service Offer
If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal!
r00t is a dedicated and highly skilled Linux Systems Administrator with over a decade of progressive experience in designing, deploying, and maintaining enterprise-grade Linux infrastructure. His professional journey began in the telecommunications industry, where early exposure to Unix-based operating systems ignited a deep and enduring passion for open-source technologies and server administration.​ Throughout his career, r00t has demonstrated exceptional proficiency in managing large-scale Linux environments, overseeing more than 300 servers across development, staging, and production platforms while consistently achieving 99.9% system uptime. He holds advanced competencies in Red Hat Enterprise Linux (RHEL), Debian, and Ubuntu distributions, complemented by hands-on expertise in automation tools such as Ansible, Terraform, Bash scripting, and Python.

Related Posts