LDAP HOWTO: OpenLDAP, 389 Directory Server, FreeIPA and SSSD
LDAP (Lightweight Directory Access Protocol) stores users, groups and other records in a tree that every machine on the network can query. On Linux today you run the directory with OpenLDAP, 389 Directory Server or FreeIPA, and clients log in through SSSD. This page shows a working setup for each, with real commands and LDIF.
The classic LDAP Implementation HOWTO (2001) used pam_ldap and nss_ldap, which are long gone; the Linux Documentation Project still keeps its related LDAP-HOWTO at tldp.org. Versions below are as of November 2026.
Choose a server
| Server | Current versions | Where it is packaged |
|---|---|---|
OpenLDAP (slapd) | 2.6 (long-term support) and 2.7 (feature release) | Debian 13 (2.6.10), Ubuntu, Fedora (openldap-servers). Not on RHEL 8 and later: Red Hat removed openldap-servers; the client tools remain. |
| 389 Directory Server | 3.x | Fedora and Debian (389-ds-base); on RHEL as part of IdM, or as the separately sold Red Hat Directory Server |
| FreeIPA (RHEL IdM) | 4.x | Server on Fedora and RHEL family; Debian 13 ships only freeipa-client |
If what you need is central logins for Linux machines, FreeIPA is usually the shortest path: it bundles 389 Directory Server, MIT Kerberos, a certificate authority and optional DNS, and joins clients in one command. Choose plain OpenLDAP or 389 DS when you need a general directory for applications, or a small server that only speaks LDAP.
OpenLDAP on Debian and Ubuntu
sudo apt install slapd ldap-utils
sudo dpkg-reconfigure slapd
dpkg-reconfigure asks for the DNS domain (which becomes the base DN, for example example.com → dc=example,dc=com), the organization name and the admin password. The admin entry is cn=admin,dc=example,dc=com.
cn=config: configuration is data
Modern slapd keeps its configuration as LDAP entries under cn=config, stored in /etc/ldap/slapd.d/ on Debian. The OpenLDAP admin guide says never to edit those LDIF files directly; change them with ldapmodify. On Debian, root can do that over the local socket (ldapi:///) with SASL EXTERNAL, without any password:
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn
The main database appears as olcDatabase={1}mdb,cn=config. To add an equality index on mail, save this as index.ldif:
dn: olcDatabase={1}mdb,cn=config
changetype: modify
add: olcDbIndex
olcDbIndex: mail eq
sudo ldapmodify -Q -Y EXTERNAL -H ldapi:/// -f index.ldif
The change takes effect immediately; there is no restart.
Add users and groups
Save this as add_content.ldif. The posixAccount and posixGroup classes hold the Unix fields (UID, GID, home, shell) that SSSD needs:
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
ou: People
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalUnit
ou: Groups
dn: cn=staff,ou=Groups,dc=example,dc=com
objectClass: posixGroup
cn: staff
gidNumber: 5000
memberUid: alice
dn: uid=alice,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: alice
cn: Alice Example
sn: Example
givenName: Alice
mail: alice@example.com
uidNumber: 10000
gidNumber: 5000
homeDirectory: /home/alice
loginShell: /bin/bash
ldapadd -x -D cn=admin,dc=example,dc=com -W -f add_content.ldif
ldappasswd -x -D cn=admin,dc=example,dc=com -W -S uid=alice,ou=People,dc=example,dc=com
ldapsearch -x -LLL -H ldap://localhost -b dc=example,dc=com '(uid=alice)' cn uidNumber
ldapwhoami -x -D uid=alice,ou=People,dc=example,dc=com -W
Blank lines separate entries, and parents must exist before children, so the order above matters. ldappasswd -S prompts for the new password and stores it hashed. Pick UID and GID numbers above the local range (10000 and up is common) so they never collide with accounts in /etc/passwd.
Turn on TLS
Clients must not send passwords in clear text, and SSSD refuses to authenticate over an unencrypted connection. Give slapd a certificate (see the SSL certificates HOWTO) by setting olcTLSCertificateFile, olcTLSCertificateKeyFile and olcTLSCACertificateFile on cn=config in one ldapmodify, making sure the openldap user can read the key. Then test StartTLS from a client:
ldapsearch -x -ZZ -H ldap://ldap.example.com -b dc=example,dc=com '(uid=alice)'
-ZZ makes the search fail unless StartTLS succeeds. Open port 389 (and 636 for LDAPS) with sudo firewall-cmd --permanent --add-service=ldap --add-service=ldaps or the matching ufw rule.
389 Directory Server
389 DS is configured with its own tools instead of hand-written LDIF for cn=config. On Fedora (or Debian with apt install 389-ds-base):
sudo dnf install 389-ds-base
Describe the instance in /root/instance.inf:
[general]
config_version = 2
[slapd]
root_password = <directory-manager-password>
[backend-userroot]
sample_entries = yes
suffix = dc=example,dc=com
sudo dscreate from-file /root/instance.inf
sudo dsctl localhost status
sudo dsidm localhost user create --uid alice --cn "Alice Example" --displayName "Alice Example" \
--uidNumber 10000 --gidNumber 5000 --homeDirectory /home/alice
sudo dsidm localhost group create # asks for the group name
sample_entries = yes adds a basic set of example entries under the suffix. With this file the instance is called localhost, the name the dsctl and dsidm commands take; root_password is the password of the directory’s administrative root account (cn=Directory Manager), so delete /root/instance.inf or remove the line once the instance exists.
FreeIPA: directory plus Kerberos
On a fresh Fedora or RHEL-family server with a static, fully qualified host name that resolves forward and backward:
sudo dnf install freeipa-server # RHEL, Alma, Rocky: ipa-server
sudo ipa-server-install
sudo firewall-cmd --permanent --add-service=freeipa-4
sudo firewall-cmd --reload
kinit admin
ipa user-add alice --first=Alice --last=Example
ipa passwd alice
The installer refuses localhost and short names, and wants the full name first in /etc/hosts (for example 10.0.0.1 ipa.example.test ipa). FreeIPA’s guide suggests a domain you control or a reserved test domain, not someone else’s. The password set by ipa passwd is temporary and must be changed at first login.
Join each client, including Debian and Ubuntu machines with freeipa-client installed:
sudo ipa-client-install --mkhomedir
It configures SSSD, Kerberos (/etc/krb5.conf), /etc/nsswitch.conf, time sync and SSH in one go. Nothing in the next section is needed for IPA clients.
Linux clients with SSSD
For a plain LDAP server (OpenLDAP or 389 DS), configure SSSD yourself. It replaces nss_ldap, pam_ldap and nslcd; Red Hat removed nss-pam-ldapd in RHEL 9 and points users to SSSD’s LDAP provider.
# Debian / Ubuntu
sudo apt install sssd-ldap libnss-sss libpam-sss
# Fedora / RHEL
sudo dnf install sssd sssd-ldap oddjob-mkhomedir
Create /etc/sssd/sssd.conf:
[sssd]
services = nss, pam
domains = example
[domain/example]
id_provider = ldap
auth_provider = ldap
ldap_uri = ldap://ldap.example.com
ldap_search_base = dc=example,dc=com
ldap_id_use_start_tls = true
ldap_tls_reqcert = demand
ldap_tls_cacert = /etc/ssl/certs/example-ca.pem
cache_credentials = true
The file must be a regular file owned by root and readable and writable only by root, or SSSD will not start:
sudo chown root:root /etc/sssd/sssd.conf
sudo chmod 600 /etc/sssd/sssd.conf
sudo systemctl enable --now sssd
sudo systemctl restart sssd
Then wire it into NSS and PAM:
# Fedora / RHEL
sudo authselect select sssd with-mkhomedir
sudo systemctl enable --now oddjobd
# Debian / Ubuntu (libnss-sss and libpam-sss already enabled the "sss" profile)
sudo pam-auth-update --enable mkhomedir
Test it:
getent passwd alice
id alice
su - alice
sudo sss_cache -E # clear SSSD’s cache after changes in the directory
If the server does not allow anonymous searches, add ldap_default_bind_dn, ldap_default_authtok_type = password and ldap_default_authtok with a read-only service account.
Mistakes to avoid
- Editing files under
slapd.d/by hand. Useldapmodify, orslapadd/slapmodifywith slapd stopped. - Setting
ldap_tls_reqcert = neverto “fix” certificate errors. Install the right CA file instead. - Reusing UID numbers that already exist locally or on NFS servers.
- Forgetting indexes on attributes you search often (
uid,uidNumber,memberUid), which makes logins slow on big directories. - Running the only directory server without replication or backups. Both OpenLDAP (syncrepl) and 389 DS support replication; FreeIPA adds replicas with
ipa-replica-install.
Sources
- OpenLDAP releases (2.6 LTS, 2.7 feature), openldap.org
- Configuring slapd (cn=config), OpenLDAP 2.6 Administrator’s Guide
- A quick-start guide, OpenLDAP 2.6 Administrator’s Guide
- Install and configure LDAP, Ubuntu Server documentation
- What to use instead of openldap-servers in RHEL 8 and later, Red Hat Knowledgebase
- Identity management changes in RHEL 9 (nss-pam-ldapd removed), Red Hat documentation
- 389 Directory Server project, port389.org
- 389 Directory Server quick start, port389.org
- FreeIPA quick start guide, freeipa.org
- About FreeIPA, freeipa.org
- Installing Identity Management (ipa-server package), RHEL 10 documentation
- ipa-client-install(1), Debian 13 manual pages
- SSSD quick start, sssd.io
- sssd-ldap(5), Debian 13 manual pages
- sssd.conf(5), Debian 13 manual pages
- authselect sssd profile, authselect project
- slapd package, Debian 13