389 Directory Server Architecture and Core Concepts

Understand 389 Directory Server architecture, including instances, ns-slapd, suffixes, backends, LMDB databases, schema, plug-ins, configuration, and replication.

Published

Updated

Read time 13 min read

Reviewed byDeepak Prasad

389 Directory Server Architecture and Core Concepts

Before you install packages or create an instance, you need a clear picture of how 389 Directory Server is put together: what an instance is, how suffixes map to backends, where configuration lives, and how an LDAP request moves through the server.

389 Directory Server is an LDAP directory server. It stores entries in a hierarchical Directory Information Tree (DIT) and answers standard LDAP operations from clients and applications. This page is conceptual. It explains architecture and terminology using inspection commands only. Installation, user management, ACIs, indexing, plug-in configuration, backup, and replication each have dedicated guides linked below.

Before you start:

Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.

389 Directory Server stack: LDAP clients connect through ns-slapd layers to an LMDB database

Read the stack top to bottom. External clients never touch the database files directly. They speak LDAP or LDAPS to ns-slapd, which handles policy and processing in-process before any read or write reaches the backend storage layer.


389 Directory Server components at a glance

The figure shows where each major concern lives inside one running instance. The front end terminates TCP connections and parses LDAP messages. Authentication and ACIs decide who is connected and what they may access. Plug-ins and schema sit in the middle of the path so extensions and attribute rules apply before backend code runs. Only the bottom layer persists entries through the configured database backend.

Component Purpose
ns-slapd Directory Server process
Instance Independently configured Directory Server deployment
Directory Information Tree Hierarchical collection of LDAP entries
Suffix Root DN of a managed directory subtree
Mapping tree Routes a target DN to a backend, referral, or chaining backend
Backend Connects a suffix to its database and indexes
LMDB Default database technology for current new instances
cn=config LDAP configuration tree
Schema Defines permitted attributes and object classes
Plug-ins Add server capabilities and processing logic
Replication agreement Controls synchronization between servers

Directory Server instances and ns-slapd

A single Linux host can run multiple Directory Server instances. Each instance is a separate deployment with its own:

  • ns-slapd process and network listeners
  • cn=config data, database files, and logs
  • TLS material, backends, and suffixes

Instance names are fixed at creation time.

An instance is not the same thing as a suffix, a backend, or the DIT. Think of the instance as the container; suffixes and backends live inside it.

List registered instances on the host:

bash
dsctl -l

The command prints one line per instance identifier:

output
slapd-localhost

Check whether the instance process is running:

bash
dsctl slapd-localhost status
output
Instance "localhost" is running

A running ns-slapd process does not by itself prove the LDAP listener is reachable. Query the Root DSE with a base-scope ldapsearch command. That is the special entry with an empty DN that advertises naming contexts, supported LDAP versions, and other server capabilities:

bash
ldapsearch -x -H ldap://localhost:10389 -s base -b "" namingContexts supportedLDAPVersion
output
dn:
namingContexts: dc=example,dc=com
supportedLDAPVersion: 2
supportedLDAPVersion: 3

The namingContexts values list suffixes this instance publishes. Use your instance port if it differs from the lab value 10389.

On RPM-based distributions, systemd tracks each instance as dirsrv@INSTANCE. Inspect the unit with systemctl:

bash
systemctl status dirsrv@localhost --no-pager

The active line confirms ns-slapd is running and shows the configuration directory passed on the command line:

output
[email protected] - 389 Directory Server localhost.
     Active: active (running)
   Main PID: 7506 (ns-slapd)
             └─7506 /usr/sbin/ns-slapd -D /etc/dirsrv/slapd-localhost -i /run/dirsrv/slapd-localhost.pid

dsctl uses the slapd-INSTANCE name; systemd uses dirsrv@INSTANCE where INSTANCE is the short name from dscreate (here localhost). Both refer to the same deployment.


Directory Information Tree, entries, DNs and suffixes

Directory data is a tree of entries. Each entry has a Distinguished Name (DN) that describes its position in the hierarchy. The leftmost component of a DN is the Relative Distinguished Name (RDN). That is the name of the entry relative to its parent.

Example DIT under dc=example,dc=com with People and Groups branches

The tree is one naming context rooted at dc=example,dc=com. Branches such as ou=People group related entries; leaf entries such as uid=user1 are the objects applications bind to or search for.

Key terms:

  • Entry — one LDAP object stored in the directory.
  • Distinguished Name — full path to an entry, for example uid=user1,ou=People,dc=example,dc=com.
  • Relative Distinguished Name — leftmost RDN component, for example uid=user1.
  • Parent and child — entries above and below in the tree.
  • Naming context or suffix — the root DN of data managed by a backend, for example dc=example,dc=com.

For each operation, the server uses the mapping tree to locate the backend responsible for the target DN. Referrals or chaining can direct the operation to another directory server.


How suffixes, backends and databases relate

Three layers are easy to confuse; keeping them separate prevents costly mistakes during planning and troubleshooting.

Mapping from suffix dc=example,dc=com through backend userroot to database storage and indexes

The suffix is what clients see in DNs and search bases. The backend is the server configuration object that owns that namespace, its indexes, and its database namespace. On current LMDB-based instances, LMDB provides the underlying storage implementation used by those backends. It is not necessarily one independently named data.mdb file per suffix.

  • A suffix is the LDAP namespace—the naming context clients bind and search under.
  • A backend is server-side configuration that serves that suffix.
  • The database stores the entries belonging to that backend.
  • Indexes accelerate searches on selected attributes.

Internally, 389 Directory Server maintains mapping-tree entries under cn=mapping tree,cn=config. A mapping-tree entry normally maps a suffix such as dc=example,dc=com to its database backend. It can also route requests to a referral or chaining backend. That routing layer is why the suffix and backend are related but remain separate configuration objects.

List suffixes configured on a running instance:

bash
dsconf slapd-localhost backend suffix list
output
dc=example,dc=com (userroot)

The parenthesized name (userroot) is the backend identifier used in further dsconf commands. Inspect backend settings for that suffix:

bash
dsconf slapd-localhost backend suffix get userroot
output
dn: cn=userroot,cn=ldbm database,cn=plugins,cn=config
nsslapd-suffix: dc=example,dc=com
nsslapd-state: backend
nsslapd-readonly: off
nsslapd-require-index: off

The nsslapd-suffix line confirms which naming context this backend serves. To see which database implementation the instance uses, read the backend configuration:

bash
dsconf slapd-localhost backend config get | grep nsslapd-backend-implement
output
nsslapd-backend-implement: mdb

A value of mdb means LMDB; bdb means Berkeley DB. On a stopped instance you can read the same attribute from dse.ldif:

bash
grep nsslapd-backend-implement /etc/dirsrv/slapd-localhost/dse.ldif
output
nsslapd-backend-implement: mdb

Backend creation and suffix design are covered in Suffixes and backends. This guide only shows how to discover what already exists.

NOTE
389 Directory Server 3.x creates new instances with LMDB by default. Older deployments may still use the deprecated Berkeley DB backend. LMDB files such as data.mdb and lock.mdb commonly appear under the instance database directory on LMDB-based installs. Verify nsslapd-backend-implement on your instance before assuming LMDB.

Configuration tree and schema

Server configuration is represented as LDAP entries under cn=config. That tree holds global settings, backend definitions, plug-in configuration, logging, password policies, and replication agreements. Administrators normally change it with dsconf (or LDAP tools) rather than by editing database files while the server is online. The on-disk dse.ldif file under the instance configuration directory is the persisted form of much of this data.

Schema is separate from ordinary suffix data. Schema definitions are loaded as server schema. They are not user entries stored in a suffix backend. Schema defines what directory entries are allowed to contain:

  • Attribute types and their syntax
  • Object classes
  • Required and optional attributes per object class
  • Matching rules used in searches and comparisons

A typical person entry might look like this in LDIF:

ldif
dn: uid=user1,ou=People,dc=example,dc=com
objectClass: inetOrgPerson
uid: user1
cn: User One
sn: One

Object classes determine which attributes the entry may carry. Custom schema design and extension are covered in Schema design and extensions, not here.

Read one global listener setting through dsconf:

bash
dsconf slapd-localhost config get nsslapd-port
output
nsslapd-port: 10389

This lab instance listens on a non-default port so it can coexist with other LDAP services. Production installs typically use 389 and 636.


How an LDAP request is processed

The easiest way to connect these components is to follow a typical LDAP operation from the client to the backend. The exact processing path varies between Bind, search, add, modify, delete, and extended operations. The figure below is a conceptual path, not a fixed sequence used identically for every operation.

LDAP request path from client connection through bind, plug-ins, schema, ACIs, backend, and response

A new LDAP connection initially has an anonymous authorization identity. If the client sends a Bind request, the server authenticates the supplied credentials and associates the resulting identity with the connection. Subsequent searches or updates are then allowed or denied according to ACIs and other server policies. Schema and ACIs gate the operation before the backend opens a transaction against the database. Post-operation plug-ins run after the backend step when a feature needs to react to a completed change.

A Bind establishes or changes the connection identity. A search evaluates ACIs and indexes before returning entries. An add or modify validates schema, enforces ACIs, then writes through the backend transaction layer. Anonymous operations remain possible when ACIs permit them. Bind is not mandatory before every search (RFC 4513).

Plug-ins can hook in before, during, or after backend work. For example, a pre-operation plug-in might reject a modify; a post-operation plug-in might update derived attributes after a group membership change. Replication plug-ins participate when changes must be recorded or forwarded to another server.

You do not need to know internal worker-thread APIs to administer the server. You do need to know where connection identity, ACIs, schema, plug-ins, and backends sit in the chain. That is where misconfiguration surfaces as bind failures, insufficient access, or slow searches.


Plug-in architecture

Many 389 Directory Server capabilities are implemented as plug-ins rather than as changes to core ns-slapd code. Plug-ins register for specific events or database types and extend the request path described above.

Plug-in Purpose
MemberOf Maintains reverse group membership
Referential Integrity Updates references when entries are renamed or deleted
DNA Allocates unique numeric values
Auto Membership Assigns entries to groups using rules
Managed Entries Creates related entries automatically
Retro Changelog Exposes change records to LDAP clients
Replication Synchronizes suffix data between instances

The Retro Changelog plug-in is separate from the internal changelog maintained for replication. Enabling a plug-in may be only the first step. Depending on the plug-in, you may also need to configure its suffix scope, managed attributes, filters, or configuration entries. The MemberOf plug-in, for example, maintains reverse membership attributes when group membership changes; if it is enabled on the wrong backend or missing required attributes, groups look correct in LDAP but applications still cannot resolve membership.

List installed plug-ins on a running instance:

bash
dsconf slapd-localhost plugin list

The command prints a long catalog of syntax, database, and feature plug-ins. A short excerpt from the lab instance includes entries such as MemberOf Plugin, Distributed Numeric Assignment Plugin, and Auto Membership Plugin. Individual plug-in chapters in the course cover configuration and verification for each feature.


Access control and authentication

Authentication and authorization are separate stages in the request path. The authorization identity on the connection starts as anonymous until a successful Bind changes it. That identity determines how ACIs evaluate each operation.

  • Authentication verifies the identity presented during a bind—who is connecting.
  • Authorization decides what that identity may read or write—which entries and attributes are visible or modifiable.
  • ACI (Access Control Instruction) is the 389 Directory Server rule format for granting or denying access to directory data.
  • Directory Manager, also called the root DN, is a special server administrative identity rather than a normal entry stored beneath the directory suffix. Regular data ACIs do not restrict its privileges. Access to this identity can instead be limited through settings such as the RootDN Access Control plug-in.

Supported bind styles you will encounter in planning and integration work include:

  • Anonymous bind
  • Simple bind with a DN and password
  • SASL mechanisms where configured
  • Certificate-based authentication for TLS client auth

Full ACI syntax and examples belong in ACI examples and SASL GSSAPI and Kerberos. This guide only maps where they fit in the architecture.


Replication architecture

Replication keeps directory data consistent across multiple instances. 389 Directory Server uses role-based replication terminology:

Role Behaviour
Supplier Accepts updates and replicates them to other servers
Hub Receives updates and forwards them without accepting normal client writes
Consumer Holds a read-only replicated copy

Replication is configured per suffix. A replication agreement describes one replication direction. The supplier initiates replication to the agreement target. Multi-supplier replication allows more than one writable supplier for the same suffix; legacy documentation sometimes called this multi-master, but current 389 Directory Server docs use multi-supplier. In a two-supplier topology, you normally configure one agreement from supplier A to supplier B and another from supplier B to supplier A.

Multi-supplier replication is eventually consistent, so replicas can temporarily return different results while changes propagate.

Replication improves availability and read scalability, but it does not replace backups. An accidental delete or incorrect modification can be replicated to every replica. Recovery therefore depends on tested backups or another documented recovery procedure, not merely on the presence of a replication changelog. Configuration commands and topology examples are in the replication chapters, not here.


Administration tools and runtime layout

The same 389 Directory Server administration tools are used across distributions. Package names, filesystem ownership, service integration, and security profiles are the parts most likely to differ.

Tool Primary purpose
dscreate Create an instance
dsctl Control and maintain a local instance offline or locally
dsconf Configure a running server over LDAP
dsidm Manage users, groups, and other directory data
Cockpit (cockpit-389-ds) Optional browser-based administration

dsctl manages local instance lifecycle and maintenance. dsconf changes server configuration. dsidm works with directory entries once organizational units and users exist.

List POSIX users through dsidm. This example binds as Directory Manager, although an appropriately authorized directory account can also be used:

bash
dsidm -b dc=example,dc=com -D "cn=Directory Manager" -W slapd-localhost user list

Because this example binds as cn=Directory Manager, enter the Directory Manager password when prompted. On a lab instance with sample entries, the command prints short user names:

output
demo_user

That output confirms dsidm is talking to directory data, not to cn=config.

Typical instance paths (RPM-based layouts)

Paths below match a standard 389-ds-base install on the RHEL family. Debian and Ubuntu use the same logical layout under slapd-INSTANCE directories, but group ownership and AppArmor profiles may differ. Check your distribution package documentation if paths do not match.

Purpose Typical location
Instance configuration /etc/dirsrv/slapd-INSTANCE/
Database data /var/lib/dirsrv/slapd-INSTANCE/db/
Logs /var/log/dirsrv/slapd-INSTANCE/
Instance service [email protected]

The lab instance stores LMDB files such as data.mdb under /var/lib/dirsrv/slapd-localhost/db/ for this deployment layout. Access, error, and audit logs live under /var/log/dirsrv/slapd-localhost/.

Never edit LMDB database files directly. For normal configuration changes, use dsconf instead of editing dse.ldif. Do not modify dse.ldif while the instance is running; manual offline changes should be limited to documented recovery or migration procedures and performed only after taking a backup.


What's Next


Summary

At runtime, one instance equals one ns-slapd process that holds cn=config, schema, plug-ins, and one or more suffix backends with their indexes and database storage. On the tested current instance that storage uses LMDB, although upgraded older deployments may use a different backend implementation. Optional replication agreements sit on top of that stack. The overview figure at the top of this page shows the same relationships in vertical form.


References

Port389 currently points administrators toward Red Hat Directory Server documentation for deployment and administration, while upstream release and installation notes cover distribution-specific differences.


Frequently Asked Questions

1. What is the difference between a 389 Directory Server instance and a suffix?

An instance is a complete Directory Server deployment on a host—its own ns-slapd process, ports, configuration, databases, logs, and certificates. A suffix is the root DN of directory data inside that instance, such as dc=example,dc=com. One instance can host multiple suffix backends; a suffix alone is not an instance.

2. Does 389 Directory Server still use Berkeley DB?

389 Directory Server 3.x creates new instances with LMDB by default. Existing instances created on older releases may still use Berkeley DB, and migration support depends on the installed version and distribution. Check the active implementation with dsconf INSTANCE backend config get and inspect nsslapd-backend-implement—a value of mdb means LMDB; bdb means Berkeley DB.

3. Is cn=config the same in OpenLDAP and 389 Directory Server?

Both products expose server configuration under an LDAP subtree named cn=config, but the object classes, attributes, storage layout, and administration tools are product-specific. You cannot import an OpenLDAP cn=config export into 389 Directory Server. See OpenLDAP vs 389 Directory Server for a side-by-side comparison.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive …