LDAP directories store users, groups and their attributes in one central place, so many applications (Nextcloud, GitLab, Gitea, Jenkins, mail servers, VPNs, Authelia, Keycloak) can authenticate against the same accounts. OpenLDAP (slapd) is the classic open-source LDAP server. This guide sets up a small directory for your apps.
Before you start: OpenLDAP is powerful, but its configuration (cn=config, LDIF) has a learning curve. For many small teams, a modern identity provider with a built-in user store (Keycloak, Authentik, or LLDAP, a lightweight LDAP server with a web UI) is simpler. See Keycloak.
Install
sudo apt update
sudo apt install slapd ldap-utils
sudo dpkg-reconfigure slapd
The reconfigure dialog asks for:
- DNS domain →
example.com(becomes the base DNdc=example,dc=com); - organisation name;
- admin password (for
cn=admin,dc=example,dc=com); - the database backend (MDB is the default).
Check it:
sudo ldapsearch -Q -LLL -Y EXTERNAL -H ldapi:/// -b cn=config dn | head
ldapsearch -x -H ldap://localhost -b dc=example,dc=com
Create the structure: OUs, users and groups
base.ldif:
dn: ou=people,dc=example,dc=com
objectClass: organizationalUnit
ou: people
dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups
users.ldif:
dn: uid=alice,ou=people,dc=example,dc=com
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
uid: alice
cn: Alice Smith
sn: Smith
givenName: Alice
mail: [email protected]
uidNumber: 10001
gidNumber: 10001
homeDirectory: /home/alice
loginShell: /bin/bash
dn: cn=developers,ou=groups,dc=example,dc=com
objectClass: groupOfNames
cn: developers
member: uid=alice,ou=people,dc=example,dc=com
Load them, and set a password:
ldapadd -x -D cn=admin,dc=example,dc=com -W -f base.ldif
ldapadd -x -D cn=admin,dc=example,dc=com -W -f users.ldif
ldappasswd -x -D cn=admin,dc=example,dc=com -W -S uid=alice,ou=people,dc=example,dc=com
Many apps use groupOfNames with a member attribute for group membership. Enable the memberOf overlay, so users get a memberOf attribute that apps can filter on.
Search and test
ldapsearch -x -H ldap://localhost -b dc=example,dc=com "(uid=alice)"
ldapwhoami -x -H ldap://localhost -D uid=alice,ou=people,dc=example,dc=com -W
Encrypt connections: LDAPS / StartTLS
Never send LDAP binds (passwords) over the network unencrypted. Get a certificate for ldap.example.com (Let’s Encrypt), copy it where openldap can read it, and configure it:
dn: cn=config
changetype: modify
replace: olcTLSCertificateFile
olcTLSCertificateFile: /etc/ldap/certs/fullchain.pem
-
replace: olcTLSCertificateKeyFile
olcTLSCertificateKeyFile: /etc/ldap/certs/privkey.pem
sudo ldapmodify -Y EXTERNAL -H ldapi:/// -f tls.ldif
Enable ldaps:/// in /etc/default/slapd (SLAPD_SERVICES="ldap:/// ldapi:/// ldaps:///"), restart slapd, and test with ldapsearch -H ldaps://ldap.example.com -x …. Automate certificate copies on renewal with a Certbot deploy hook. See Let’s Encrypt.
Access control and binding
- Create a read-only service account (e.g.
cn=readonly,dc=example,dc=com) for applications to search the directory. Don’t give apps the admin DN. - Set ACLs (
olcAccess) so users can change their own password, the service account can read but not see password hashes, and everything else is restricted. - Firewall: allow 389 and 636 only from your application servers or a VPN. Never expose LDAP to the whole internet. See UFW.
Connect applications
Typical settings in an app’s LDAP configuration:
| Setting | Example |
|---|---|
| Server | ldaps://ldap.example.com:636 |
| Bind DN | cn=readonly,dc=example,dc=com |
| User base | ou=people,dc=example,dc=com |
| User filter | (&(objectClass=inetOrgPerson)(uid=%s)) |
| Group filter | (memberOf=cn=developers,ou=groups,dc=example,dc=com) |
Linux logins against LDAP use SSSD.
Management tools
- phpLDAPadmin or LDAP Account Manager (LAM): web UIs. Protect them behind authentication or a VPN.
- Apache Directory Studio: a desktop LDAP browser.
Backups
sudo slapcat -n 0 > /backups/ldap-config-$(date +%F).ldif # configuration
sudo slapcat -n 1 > /backups/ldap-data-$(date +%F).ldif # directory data
Restore with slapadd (with slapd stopped). See backup strategy.
Quick reference
| Task | Command |
|---|---|
| Reconfigure | sudo dpkg-reconfigure slapd |
| Add entries | ldapadd -x -D cn=admin,… -W -f file.ldif |
| Search | ldapsearch -x -b dc=example,dc=com "(uid=alice)" |
| Set password | ldappasswd -x -D cn=admin,… -W -S uid=… |
| Modify config | ldapmodify -Y EXTERNAL -H ldapi:/// -f file.ldif |
| Back up | slapcat -n 0 / slapcat -n 1 |
Related: Authelia and least privilege.