Below is a comprehensive, step-by-step guide to deploying the 389 Directory Server on Rocky Linux VPS instances, and configuring a separate Rocky Linux machine as an LDAP client.
It covers everything from package installation and initial instance setup, through firewall and TLS configuration, to client-side LDAP querying and optional system authentication via SSSD.
What is 389 Directory Server?
389 Directory Server is an open-source, enterprise-class Lightweight Directory Access Protocol (LDAP) server developed by the Fedora Project and maintained by Red Hat. It provides a robust, scalable directory service for storing and retrieving user, group, device, and policy information across your organization.
Key Characteristics
- Standards-Compliant LDAPv3
Fully implements the IETF’s LDAP version 3 specification, including support for extended operations, controls, and mandatory features such as referrals and schema management. - Multi-Master Replication
Allows you to run multiple writable directory servers that stay in sync, improving availability and enabling geographically distributed deployments. - Dynamic Schema
You can define and modify object classes and attributes without restarting the server, making it easy to evolve your directory’s data model over time. - Access Control
Fine-grained ACLs let you specify exactly who can read, write, or manage each branch of the directory tree. - High Performance & Scalability
Tunable back-end caches, connection pooling, and support for millions of entries make it suitable for large-scale environments. - TLS/SSL & SASL Authentication
Secure your traffic with TLS (LDAPS) or StartTLS, and integrate with Kerberos, SASL, or SASL-GSSAPI for strong authentication. - Administration Tools
- Command-line utilities (e.g.,
dsconf
,ldapadd
,ldapsearch
) for scripted management. - Web-based console (cockpit-389-ds) for visual configuration, monitoring, and replication setup.
Typical Use Cases
- Centralized Identity Store
Maintain all user and group credentials in one place for authentication (e.g., SSH, VPNs, applications). - Configuration & Policy Distribution
Store software configuration profiles, host definitions, or network policies and have clients query dynamically. - Certificate Authority Integration
Back an enterprise PKI: store certificates, CRLs, and key recovery information. - Address Book & Contact Services
Provide a shared global address book for email clients or unified communications systems.
Architecture Overview
┌────────┐ ┌────────────┐ ┌─────────────┐
│ Client │ ──LDAP──▶ 389-DS ──Backend─▶ DB Backend │
└────────┘ └────────────┘ └─────────────┘
(Berkeley DB or LDIF)
- Listener Layer handles LDAP/SASL/TLS.
- Dispatcher & Replication coordinates data sync across peers.
- Plug-in Framework for custom password policies, referrals, or logging.
- Storage Layer uses either an on-disk database (Berkeley DB) or file-based LDIF for small deployments.
Why Choose 389 Directory Server?
- Open-Source & Free under the LGPLv2.1+ license.
- Enterprise-Grade features rival proprietary directory products.
- Extensible & Scriptable, with rich tooling for automation.
- Broad Adoption, underpinning Red Hat IDM (Identity Management) and many Fedora/Red Hat–based environments.
By installing 389 Directory Server, you gain a flexible, secure, and highly available backbone for identity and directory services in both small and large infrastructures.
-
Overview
The 389 Directory Server is an enterprise-class LDAP server. In this guide you will:
- Install and configure a 389 Directory Server instance on a Rocky Linux VPS.
- Open the necessary ports and enable the service at boot.
- Generate or install TLS certificates for secure LDAPS.
- Configure a separate Rocky Linux machine as an LDAP client for querying and (optionally) system authentication.
-
Prerequisites
- Two Rocky Linux VPS servers (Rocky Linux 8/Rocky Linux 9) (we’ll call them ldap-server and ldap-client).
- Root or sudo access on both.
- A registered fully-qualified domain name (e.g.
example.com
) pointing DNS records forldap.example.com
→ ldap-server’s IP (See Guide: How to Point a Domain to Your VPS Server) - Basic familiarity with the Linux command line (shell) and editing files (e.g.
nano
).
-
Hostname and DNS
On ldap-server:
sudo hostnamectl set-hostname ldap.example.com
Ensure
/etc/hosts
includes (if not using public DNS):192.0.2.10 ldap.example.com ldap
On ldap-client, set its hostname similarly (e.g.
ldap-client.example.com
). -
Install 389 Directory Server
On ldap-server, enable the AppStream module (if needed) and install:
sudo dnf module enable 389-ds -y sudo dnf install -y 389-ds-base sudo dnf copr enable @389ds/389-directory-server -y sudo dnf install -y cockpit-389-ds
- 389-ds-base provides the core server.
- cockpit-389-ds adds the Web-console (optional).
-
Configure Your Directory Instance
Use the interactive setup script:
sudo dscreate interactive
You’ll be prompted for:
- Suffix (e.g.
dc=example,dc=com
) - Directory Manager DN (
cn=Directory Manager
) - A password for Directory Manager
- Port settings (389 for LDAP, 636 for LDAPS)
- Admin port (9830) if you installed the console
It will write your instance to
/etc/dirsrv/slapd-ldap/
.Tip: To re-run or script it non-interactively, use
sudo dscreate create-template
. - Suffix (e.g.
-
Enable & Start the Service
sudo systemctl enable dirsrv@slapd-ldap.service sudo systemctl start dirsrv@slapd-ldap.service
Check health:
sudo systemctl status dirsrv@EXAMPLE-COM.service
-
Firewall Configuration
Open LDAP ports:
sudo firewall-cmd --add-service=ldap --add-service=ldaps --permanent sudo firewall-cmd --reload
If using the admin console:
sudo firewall-cmd --add-port=9830/tcp --permanent sudo firewall-cmd --reload
-
Verify Basic LDAP Connectivity
From ldap-server itself:
ldapsearch -x -H ldap://localhost -b dc=example,dc=com \ -D "cn=Directory Manager" -W "(objectClass=*)"
Enter your Directory Manager password; you should see your base entry.
-
Configure TLS/SSL for LDAPS (with Certbot)
-
Prerequisites
- HTTP access
– Port 80 must reach your 389-DS host (for the HTTP-01 challenge).
– If you cannot expose port 80, skip to “DNS-01 challenge” below. - Install Certbot:
sudo dnf install -y epel-release sudo dnf install -y certbot
- Ensure your DNS
–ldap.example.com
points to your 389-DS VPS.
– (If you’ll use DNS-01, you’ll need API credentials for your DNS provider.)
- HTTP access
-
One-Time: Issue Your First Certificate
-
Stop any service on port 80 (if needed)
Certbot’s standalone plugin will bind to port 80. If Apache/Nginx is running, either stop it temporarily or use the webroot plugin.
sudo systemctl stop httpd # or nginx, whatever you use
-
Obtain a cert via HTTP-01
sudo certbot certonly \ --standalone \ -d ldap.example.com \ --agree-tos \ --email admin@example.com \ --non-interactive
This creates:
/etc/letsencrypt/live/ldap.example.com/fullchain.pem
/etc/letsencrypt/live/ldap.example.com/privkey.pem
-
(If HTTP-01 won’t work) DNS-01 challenge
sudo certbot certonly \ --dns-YOURDNSPLUGIN \ --dns-YOURDNSPLUGIN-credentials /etc/letsencrypt/YOURDNS.ini \ -d ldap.example.com \ --agree-tos \ --email admin@example.com \ --non-interactive
-
-
Deploying the Cert to 389-DS
Create a deploy hook that Certbot will run after every issuance or renewal.
- Hook script
Save as/etc/letsencrypt/renewal-hooks/deploy/389ds.sh
:#!/bin/bash set -e INSTANCE="EXAMPLE-COM" DS_DIR="/etc/dirsrv/slapd-${INSTANCE}/certs" LIVE_DIR="/etc/letsencrypt/live/ldap.example.com" # Copy new cert+key cp "${LIVE_DIR}/fullchain.pem" "${DS_DIR}/server.crt" cp "${LIVE_DIR}/privkey.pem" "${DS_DIR}/server.key" # Fix permissions chown dirsrv:dirsrv "${DS_DIR}/server."* chmod 640 "${DS_DIR}/server."* # Restart 389-DS so it picks up the new cert systemctl restart "dirsrv@${INSTANCE}.service"
- Make executable:
sudo chmod +x /etc/letsencrypt/renewal-hooks/deploy/389ds.sh
- Manually trigger a dry-run:
sudo certbot renew --dry-run
You should see your hook execute without errors.
- Hook script
-
Automating Renewal
Certbot installs a systemd timer or cron job by default on Rocky Linux. After the above hook is in place, every time
certbot renew
runs (twice daily), it will:- Check if the cert is due for renewal (–30 days before expiry).
- If renewed, call your
389ds.sh
hook to install and reload.
You can inspect the timer with:
systemctl status certbot-renew.timer
-
(Optional) Monitoring & Alerts
If you’d like to be notified on failures:
- Email: Add
--deploy-hook 'mail -s "389-DS TLS renewed" you@example.com'
to your renewal command. - Logging: Certbot logs to
/var/log/letsencrypt/letsencrypt.log
.
- Email: Add
-
-
Set Up the LDAP Client
On ldap-client, install the OpenLDAP tools:
sudo dnf install -y openldap-clients
Create
/etc/openldap/ldap.conf
:URI ldaps://ldap.example.com BASE dc=example,dc=com TLS_CACERT /etc/pki/tls/certs/ca-bundle.crt
You can copy your server’s CA cert into
/etc/pki/tls/certs/
if you used a self-signed cert. -
Test LDAP Queries from the Client
ldapsearch -x -LLL \ -H ldaps://ldap.example.com \ -b dc=example,dc=com "(objectClass=organizationalRole)" namingContexts
You should see your
dc=example,dc=com
entry returned. -
(Optional) System Authentication via SSSD
If you want users in LDAP to be able to log into ldap-client, use SSSD:
- Install:
sudo dnf install -y sssd sssd-tools oddjob-mkhomedir
- Configure
/etc/sssd/sssd.conf
:[sssd] services = nss, pam config_file_version = 2 domains = example.com domain/example.com] id_provider = ldap auth_provider = ldap ldap_uri = ldaps://ldap.example.com ldap_search_base = dc=example,dc=com ldap_tls_reqcert = demand enumerate = true [nss] filter_groups = root filter_users = root
Set permissions and start:
sudo chmod 600 /etc/sssd/sssd.conf sudo systemctl enable sssd sudo systemctl start sssd sudo authconfig --enablesssd --enablesssdauth --update
- Automatic home directories:
sudo authconfig --enablemkhomedir --update
- Test:
getent passwd some-ldap-user ssh some-ldap-user@localhost
- Install:
-
Troubleshooting Tips
-
- Logs on server:
/var/log/dirsrv/slapd-EXAMPLE-COM/errors
- dsconf can show and modify settings:
dsconf -D "cn=Directory Manager" -W ldap status
- Logs on server:
- Firewall: double-check
firewall-cmd --list-all
. - Certificates: ensure the client trusts your CA or system bundle.
-
-
Next Steps
- Populate your DIT with organizational units, groups, and users via
ldapadd
or the 389-ds web console. - Consider replication for high availability.
- Regularly backup your DIT using
db2bak
.
- Populate your DIT with organizational units, groups, and users via
With these steps, you’ll have a fully functional 389 Directory Server on Rocky Linux, secured via LDAPS, and a Rocky Linux client able to query (and even authenticate against) it. Feel free to expand with custom schemas, password policies, or replication as your directory grows!