Serving the directory (LDAP)

DPF can be the directory for an installation — most installs have no Active Directory, and an identity stack that only federates outward leaves them with nothing. This page is how an operator turns that on.

It is off by default. An install does not start serving an identity protocol because it was upgraded.

Design: Directory Service — Identity Absorption §9.1.

What you get

A read-only LDAPS listener that publishes the Principal spine as a directory tree: people, agents, services and groups. Clients bind and search. They cannot write — add, modify and delete are refused, not merely unimplemented, because the directory is authoritative for being derived from the spine, not for being a second place to edit identity.

Group membership projects organizational structure. It is not an authorization API, and nothing derives permission from it.

Prerequisites

The organization CA must be bootstrapped. The listener serves LDAPS from the organization’s own PKI and there is no self-signed fallback. If you have not already set up organization HTTPS:

bash scripts/bootstrap-organization-pki.sh --mode authority --hostname <your-host-name-or-IP>

That writes authority.crt, authority.key and root_ca.crt into DPF_PKI_DIR (default ~/.dpf/pki) and records the trust settings in .env. The listener reuses that material — the same certificate the portal already serves HTTPS with — so there is no second certificate to manage or renew.

An Organization must exist. The directory is the organization’s namespace; the base DN derives from it. A fresh install with no organization has nothing to publish, and the listener will say so rather than binding an empty tree.

Turning it on

Add to your install’s .env:

DPF_LDAP_ENABLED=1

Then apply it through the governed upgrade path — /ops/self-upgrade in the portal. That owns quiescence, recovery points and rollback; do not rebuild the portal by hand.

Confirm at Platform → Identity → Directory. The “Directory listener” card reads one of three things, and only one of them means clients can bind:

Card reads Meaning
Serving LDAPS A client can bind right now, on the port shown.
Not served DPF_LDAP_ENABLED is unset. Nothing is bound.
Failed to start It was turned on and could not start. The reason is shown.

“Failed to start” is deliberately not the same as “Not served”. A directory that was configured and died must not look like one nobody asked for.

Checking it with a real client

ldapsearch -H ldaps://127.0.0.1:636 -x -D "uid=<principalId>,ou=people,<baseDn>" -W -b "<baseDn>" "(objectClass=*)"

The base DN is shown on the same Directory page. If your client does not already trust the organization CA, point it at the root:

LDAPTLS_CACERT=~/.dpf/pki/root_ca.crt ldapsearch -H ldaps://127.0.0.1:636 -x -b "<baseDn>" "(objectClass=*)"

Settings

Variable Default What it does
DPF_LDAP_ENABLED 0 Serve the directory at all.
DPF_LDAP_PORT 636 Listen port. 636 is the standard LDAPS port.
DPF_LDAP_BIND_ADDRESS 127.0.0.1 Host interface the port is published on.
DPF_LDAP_REQUIRE_CLIENT_CERTIFICATE 0 Require mTLS. Stronger, but only for clients that can present a certificate.
DPF_LDAP_TLS_CERT_PATH /dpf-state/pki/authority.crt Server certificate.
DPF_LDAP_TLS_KEY_PATH /dpf-state/pki/authority.key Server key.
DPF_LDAP_TLS_CA_PATH /dpf-state/pki/root_ca.crt Org CA, used to verify client certificates.

Letting other hosts bind

The port is published on loopback by default, matching the step-ca overlay: a directory other machines can reach is a deliberate choice, not a default. To serve the LAN, set DPF_LDAP_BIND_ADDRESS to one private IP of this host — and make sure the certificate’s SANs actually cover the name clients will use, or their TLS verification will fail.

If you moved the PKI directory

The three TLS paths default to /dpf-state/pki/…, which resolves because DPF_PKI_DIR defaults to ~/.dpf/pki and DPF_STATE_DIR (~/.dpf) is already mounted read-only into the portal. If you set DPF_PKI_DIR somewhere outside DPF_STATE_DIR, set all three paths explicitly to a location the container can read. The listener refuses to start rather than falling back to a self-signed certificate, so a wrong path is loud, not silent.

When it will not start

Every one of these shows on the Directory page as Failed to start, with the reason:

A listener that cannot start does not take the portal down. Everything else keeps serving, and the failure is reported rather than fatal.

What this does not do

SAML, OIDC and SCIM are each their own surface and their own decision, and are deliberately not part of this. LDAP write operations are refused by design.