389 Directory Server stores server certificates, CA certificates, and private keys in an instance-specific NSS database under the configuration directory. Nicknames such as Server-Cert identify entries inside that database; trust flags tell NSS how to treat CA material; and the active server nickname (nsSSLPersonalitySSL) decides which certificate LDAPS and STARTTLS present to clients.
This guide covers the full certificate lifecycle after TLS is already working: inventory, expiry checks, backup, CSR generation, renewal and replacement, CA chain maintenance, nickname changes, NSS password handling, safe removal, and recovery from expired or broken material.
Before you start:
- Configure TLS, STARTTLS, and LDAPS — first TLS deployment, listener ports, and client trust
- dsconf commands — online security configuration
- dsctl commands — offline NSS and instance operations
Server-Cert.
Tested on: Rocky Linux 10.2; 389 Directory Server 3.2.0.
The lab uses instance ldap1 on ldap1.example.com (LDAP 389, LDAPS 636) and a second instance ldap2 on ports 1389 and 1636, each with its own NSS database under /etc/dirsrv/slapd-<instance>/.
Understand the Directory Server certificate store
| Component | Purpose |
|---|---|
| Server certificate | Identifies the LDAP server to TLS clients |
| Private key | Proves ownership of the server certificate |
| CA certificate | Lets Directory Server and clients validate the issuing authority |
| Intermediate CA | Connects the server certificate to a trusted root |
| Certificate nickname | Names a certificate or key pair inside the NSS database |
| Trust flags | Define how NSS trusts a CA certificate (see table below) |
| NSS database | Stores certificates and private keys (cert9.db, key4.db) |
pwdfile.txt |
Supplies the NSS database password to administrative tools |
pin.txt |
Supplies the token name and NSS password when Directory Server starts |
| Flags | Meaning |
|---|---|
c,, |
Recognize the certificate as a valid CA without necessarily making it an explicit trust anchor |
C,, |
Trust the CA to issue server or replication-peer certificates |
T,, |
Trust the CA to issue client certificates |
CT,, |
Trust the CA for both server and client-certificate validation |
Give the root or intended trust anchor C,, when it is trusted to issue server certificates. Intermediate certificates commonly use c,, so NSS recognizes them as valid CA certificates without automatically treating every intermediate as a trust anchor. Add T only when the CA is authorized to issue client certificates used for TLS EXTERNAL authentication.
The NSS database is created during instance setup and lives with the instance configuration:
/etc/dirsrv/slapd-INSTANCE/Typical files in that directory include cert9.db, key4.db, pin.txt, pwdfile.txt, ca.crt, and Server-Cert.crt. After you generate a renewal request, Server-Cert.csr appears as well. A dscreate instance on the same host may share a host-level signing CA under /etc/dirsrv/ssca/ while each instance keeps its own NSS store.
dscreate stores the NSS password in pwdfile.txt for administrative tools and in pin.txt for automatic token unlock at instance startup. Both files are created during instance setup.
List installed certificates
Start with the supported Directory Server tools. They read the same NSS database the server uses at runtime.
List server certificates in the instance NSS database:
dsconf ldap1 security certificate listSample output:
Certificate Name: Server-Cert
Subject DN: CN=ldap1.example.com,givenName=6d6a490c-bebd-41c4-8552-20cb270367ed,O=testing,L=389ds,ST=Queensland,C=AU
Issuer DN: CN=ssca.389ds.example.com,O=testing,L=389ds,ST=Queensland,C=AU
Expires: 2028-07-15 08:12:48
Trust Flags: u,u,uList installed CA certificates and inspect their trust flags:
dsconf ldap1 security ca-certificate listSample output:
Certificate Name: Self-Signed-CA
Subject DN: CN=ssca.389ds.example.com,O=testing,L=389ds,ST=Queensland,C=AU
Issuer DN: CN=ssca.389ds.example.com,O=testing,L=389ds,ST=Queensland,C=AU
Expires: 2028-07-15 06:33:15
Trust Flags: C,,Show the certificate clients receive on LDAPS and STARTTLS:
dsctl ldap1 tls show-server-certThe command prints the full PEM details, including serial number, validity, SAN entries, and fingerprints. In this lab the active entry is Server-Cert with SAN ldap1.example.com.
For one nickname, dsconf security certificate get returns a shorter summary:
dsconf ldap1 security certificate get Server-CertSample output:
Certificate Name: Server-Cert
Subject DN: CN=ldap1.example.com,givenName=6d6a490c-bebd-41c4-8552-20cb270367ed,O=testing,L=389ds,ST=Queensland,C=AU
Issuer DN: CN=ssca.389ds.example.com,O=testing,L=389ds,ST=Queensland,C=AU
Expires: 2028-07-15 08:12:48
Trust Flags: u,u,uConfirm whether each server certificate has a matching private key:
dsconf ldap1 security key listSample output:
Cipher: rsa
Key Id: 5f2a98f53c0b3ce916e05bac228e517ae11f7b57
State: NSS Certificate DB:Server-CertA State of (orphan) means a private key exists without a linked certificate nickname. That is common after generate-server-cert-csr until the signed certificate is imported.
For the local ldap2 instance, use the instance name when local resolution is configured:
dsconf ldap2 security certificate listOn the tested lab build, that command can fail against ldap2 with expected str, bytes or os.PathLike object, not NoneType while ldap1 succeeds. When dsconf cannot list server certificates, inspect the local NSS database instead:
certutil -L -d /etc/dirsrv/slapd-ldap2/Sample output:
Certificate Nickname Trust Attributes
SSL,S/MIME,JAR/XPI
Self-Signed-CA CT,,
Server-Cert u,u,uThen confirm which certificate ldap2 would present on LDAPS:
dsctl ldap2 tls show-server-certTo target the non-default LDAPS listener explicitly, supply the LDAP URL and read the Directory Manager password from a file with -y:
LDAPTLS_CACERT=/root/ldap2-ca-chain.pem dsconf -D "cn=Directory Manager" -y /root/dm.pw ldaps://ldap2.example.com:1636 security certificate listRHDS distinguishes local instance-name resolution from explicitly supplied LDAP URLs. When dsconf cannot reach a remote listener, inspect the local NSS database with dsctl ldap2 tls show-server-cert or certutil -L -d /etc/dirsrv/slapd-ldap2/.
Recent dsconf and dsctl builds add options over time; run --help on your installed version before you script nickname selection.
Check certificate expiration
Inspect the active server certificate locally:
dsctl ldap1 tls show-server-certRead the Not Before and Not After lines and confirm the DNS name SAN covers the hostname clients use.
Inspect only the leaf certificate the listener presents with OpenSSL:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -serial -ext subjectAltNameSample output:
subject=C=AU, ST=Queensland, L=389ds, O=testing, GN=6d6a490c-bebd-41c4-8552-20cb270367ed, CN=ldap1.example.com
issuer=C=AU, ST=Queensland, L=389ds, O=testing, CN=ssca.389ds.example.com
notBefore=Jul 15 08:12:48 2026 GMT
notAfter=Jul 15 08:12:48 2028 GMT
serial=CAD43C73
X509v3 Subject Alternative Name:
DNS:ldap1.example.comThat pipeline shows leaf details only; it does not validate the complete chain.
Before renewal, record:
- Expiration date and remaining window
- SAN hostname coverage
- Issuer and complete chain files on disk
- Active nickname (
dsconf ldap1 security rsa get) - Client trust store contents for applications that pin CAs
Back up certificates before making changes
Current RHDS 13 backups created by dsconf backup create or dsctl db2bak include the instance configuration, NSS certificate database, and custom schema under the backup's config_files/ directory. Those configuration files are backed up but are not restored automatically with the database. Keep an additional off-host PKCS#12 export and verify every backup contains cert9.db, key4.db, and the required configuration files.
dsconf backup create is the online method; dsctl db2bak is offline.
Create an online backup:
dsconf ldap1 backup createSample output:
The backup create task has finished successfullyList the backed-up configuration files to confirm NSS material is present:
ls /var/lib/dirsrv/slapd-ldap1/bak/ldap1-*/config_files/Sample output:
cert9.db
certmap.conf
dse.ldif
key4.db
pin.txt
pwdfile.txt
schema
slapd-collations.confIn a replicated deployment, restoring an online backup clears the replication changelog and requires the replica to be reinitialized. Use an offline dsctl INSTANCE db2bak backup when avoiding that recovery step is important, accepting the required downtime.
A direct tar command archive can remain as a supplemental host-level backup. Stop the instance first so NSS files are not changing during the archive:
dsctl ldap1 stopI'll set umask 077 before creating the archive so new files are not world-readable:
umask 077Create the archive with ACLs, extended attributes, and SELinux labels preserved:
tar --acls --xattrs --selinux -czpf /root/slapd-ldap1-config-$(date +%F-%H%M).tar.gz -C /etc/dirsrv slapd-ldap1I'll set mode 600 on the finished archive with the chmod command because it contains private keys and NSS password files:
chmod 600 /root/slapd-ldap1-config-*.tar.gzStart the instance again after the backup completes:
dsctl ldap1 startAlso record in your change-management system:
- Current server certificate nickname
- CA trust flags
dsconf ldap1 security rsa getoutput- Certificate fingerprints from
dsctl ldap1 tls show-server-cert - Location of PKCS#12 and backup archives (not the plaintext NSS password)
Export the server certificate and private key
Export the active server certificate and private key into a password-protected PKCS#12 file with pk12util. Store the export password in a file and pass it with lowercase -w (read password from file). Pass the NSS token password with lowercase -k (read from file):
install -m 600 /dev/null /root/pk12-export.pwWrite the export password into /root/pk12-export.pw with an editor, then export:
pk12util -d /etc/dirsrv/slapd-ldap1 -n "Server-Cert" -o /root/ldap1-server-cert-backup.p12 -w /root/pk12-export.pw -k /etc/dirsrv/slapd-ldap1/pwdfile.txtSample output:
pk12util: PKCS12 EXPORT SUCCESSFULI'll set mode 600 on the PKCS#12 export because it contains the private key:
chmod 600 /root/ldap1-server-cert-backup.p12Store the .p12 password in an approved secret manager. The export contains the selected certificate and private key. It may also contain certificates from a chain that NSS can build, but do not rely on that without checking pk12util -l. Preserve CA and intermediate certificates separately as well.
List the export contents when you need to verify:
pk12util -l /root/ldap1-server-cert-backup.p12 -w /root/pk12-export.pwSample output:
Key(shrouded):
Friendly Name: Server-Cert
...
Certificate:
Data:
Version: 3 (0x2)
...
Friendly Name: Server-CertExact formatting varies by NSS version; confirm that both a certificate and a private key entry appear.
Export only the public certificate PEM when you do not need the private key:
dsctl ldap1 tls export-cert Self-Signed-CA --output-file /root/self-signed-ca.pemThat command exits silently on success; the PEM file should begin with -----BEGIN CERTIFICATE-----.
Generate a certificate renewal CSR
I'll generate a new key pair and CSR inside the instance NSS database:
dsctl ldap1 tls generate-server-cert-csr --subject "CN=ldap1.example.com,O=Example" ldap1.example.comSample output:
/etc/dirsrv/slapd-ldap1/Server-Cert.csrThe CSR file lands in the instance configuration directory; the matching private key stays in key4.db until you import the signed certificate.
Review the CSR before you submit it to the CA:
openssl req -in /etc/dirsrv/slapd-ldap1/Server-Cert.csr -noout -textSample output:
Certificate Request:
Data:
Version: 1 (0x0)
Subject: O=Example, CN=ldap1.example.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
...
Requested Extensions:
X509v3 Subject Alternative Name:
DNS:ldap1.example.comConfirm the common name, SAN list, and key size match your CA request template.
This command writes a new private key into the NSS database. Do not run it while another backup, certificate import, PKCS#12 operation, or NSS maintenance task is modifying the same database.
dsconf can list and display CSRs as well. List pending CSRs in the instance NSS database:
dsconf ldap1 security csr listShow the CSR details for the Server-Cert nickname:
dsconf ldap1 security csr get Server-CertAfter the CA returns a signed certificate, delete the CSR file when you no longer need it:
dsconf ldap1 security csr del Server-CertRenew a certificate using the existing NSS private key
After the CA signs the CSR, confirm that the signed certificate contains the same public key before you import it. Hash the public key from the CSR:
openssl req -in /etc/dirsrv/slapd-ldap1/Server-Cert.csr -noout -pubkey | sha256sumHash the public key from the signed certificate and compare the two lines:
openssl x509 -in /root/ldap1-renewed.crt -noout -pubkey | sha256sumThe hashes must match.
Import the CA chain before the leaf certificate. Start with the root and set intentional trust:
dsconf ldap1 security ca-certificate add --file /root/example-root-ca.crt --name "Example-Root-CA"Mark the root as trusted to issue server certificates:
dsconf ldap1 security ca-certificate set-trust-flags "Example-Root-CA" --flags "C,,"Sample output:
Successfully edited certificate trust flagsImport intermediate CA certificates as required, then import the signed leaf certificate once under a new nickname so the current Server-Cert keeps working until you test the replacement:
dsconf ldap1 security certificate add --file /root/ldap1-renewed.crt --name "ldap1-2027"Sample output:
Successfully added certificateConfirm the private key is linked:
dsconf ldap1 security key listWhen the new nickname shows State: NSS Certificate DB:ldap1-2027 instead of (orphan), the import matched the CSR key.
Sample output:
Key Id: ff29368fc2b47c682243b6decc4ed5b1786cb704
State: NSS Certificate DB:ldap1-2027The signed certificate must be issued from the same CSR public key. certutil -S in the host SSCA database creates a new key and does not satisfy this check.
Switch the active nickname:
dsconf ldap1 security rsa set --nss-cert-name "ldap1-2027"Sample output:
Successfully updated security configuration (nsSSLToken)Alternative to the preceding staged import and rsa set commands: when the nickname has not already been imported, add and activate it in one operation:
dsconf ldap1 security certificate add --file /root/ldap1-renewed.crt --name "ldap1-2027" --primary-certChoose either the staged workflow or this one-step workflow. Do not run certificate add --primary-cert after ldap1-2027 already exists.
Keep the previous Server-Cert nickname in the NSS database until LDAPS, STARTTLS, replication, and application clients succeed with the new material.
dsconf security certificate list but dsconf security key list still shows only (orphan) keys. LDAPS fails when you point nsSSLPersonalitySSL at that nickname. Always confirm key linkage before you switch the active certificate.
Replace a certificate and private key created externally
When the CSR and private key were created outside Directory Server, such as through Let's Encrypt, a corporate HSM workflow, or openssl req -newkey, import the PEM pair together while the instance is stopped. Stop ldap2 so the import does not race with a running server:
dsctl ldap2 stopImport the external certificate and private key into the instance NSS database:
dsctl ldap2 tls import-server-key-cert /root/ldap2-external.crt /root/ldap2-external.keyStart the instance again so Directory Server reloads the updated NSS material:
dsctl ldap2 startdsctl edits the local NSS store directly. Direct NSS changes made by another process are not synchronized reliably with the running server, so stop the instance before import and start it afterward.
Confirm the new active certificate:
dsctl ldap2 tls show-server-certSample output:
Issuer: "CN=ldap2.example.com"
Subject: "CN=ldap2.example.com"
DNS name: "ldap2.example.com"By default, dsctl tls import-server-key-cert targets the Server-Cert nickname. Current builds may support --nickname; check dsctl INSTANCE tls import-server-key-cert --help. Do not pass a chain bundle to this command. Import the leaf certificate and key first, then add CA certificates separately with dsconf.
Import and update the CA certificate chain
Import a CA or intermediate that signs server certificates:
dsconf ldap1 security ca-certificate add --file /root/example-ca.crt --name "Example-CA"Mark the CA as trusted to issue server certificates:
dsconf ldap1 security ca-certificate set-trust-flags "Example-CA" --flags "C,,"Sample output:
Successfully edited certificate trust flagsAdd T to the flags only when the CA also issues client certificates for TLS EXTERNAL binds (CT,,).
Import an intermediate CA and assign c,, so NSS recognizes it as a valid CA without making it an explicit trust anchor:
dsconf ldap1 security ca-certificate add \
--file /root/example-intermediate-ca.crt \
--name "Example-Intermediate-CA"Apply the intermediate trust flags:
dsconf ldap1 security ca-certificate set-trust-flags "Example-Intermediate-CA" --flags "c,,"The root and required intermediate CA certificates must be available to Directory Server so NSS can build the server certificate chain. Clients normally trust the root or another intended trust anchor. Required intermediate certificates must either be sent by the server during the handshake or be available in the client certificate store; they should not automatically be configured as client trust anchors. A dsconf NSS import does not necessarily update the convenience PEM file /etc/dirsrv/slapd-ldap1/ca.crt. Export the trusted CA nickname or maintain a known client bundle:
dsctl ldap1 tls export-cert "Self-Signed-CA" --output-file /root/example-root-ca.pemSelect the active server certificate
After the renewal workflow imports ldap1-2027 and links it to the CSR private key, switch the active nickname to that certificate. The active server certificate is nsSSLPersonalitySSL under cn=RSA,cn=encryption,cn=config. List available server nicknames:
dsconf ldap1 security certificate listBefore you switch nicknames, confirm:
- The nickname exists in the NSS database
dsconf ldap1 security key listlinks a private key to that nickname- The certificate includes the LDAP hostname in SAN
- The certificate is valid for server authentication
Switch the active nickname:
dsconf ldap1 security rsa set --nss-cert-name "ldap1-2027"Verify the active nickname:
dsconf ldap1 security rsa getSample output:
nssslactivation: on
nssslpersonalityssl: ldap1-2027
nsssltoken: internal (software)Keep the old Server-Cert nickname until the new one passes LDAPS and STARTTLS tests.
Reload or restart Directory Server
Listener changes require an instance restart. That includes first enabling nsslapd-security, changing the secure port, or disabling the plain-text port, as described in the TLS chapter.
Certificate replacement through dsconf is different. RHDS 13.2 on RHEL 10.2 documents online TLS certificate refresh for packages that provide dsconf INSTANCE config refresh-certs. Upstream 389 DS completed the corresponding CLI work across the 3.2.0 and 3.2.1 development cycle. Therefore, test for the command instead of relying only on the displayed 389 DS version.
Check whether your build exposes online refresh:
dsconf ldap1 config --helpSample output on the tested Rocky Linux 10.2 package:
usage: dsconf [-v] [-j] instance config [-h] {get,add,replace,delete} ...When refresh-certs appears in that help output, switch the active nickname and refresh TLS material online without restarting:
dsconf ldap1 security rsa set --nss-cert-name "ldap1-2027"Reload the in-memory certificate store for new TLS connections:
dsconf ldap1 config refresh-certsThe refreshed material is used for new TLS connections; existing connections are not explicitly closed, although a changed CA can cause some clients to disconnect.
When refresh-certs is not available, set the active nickname and restart the instance so the listener loads the new certificate:
dsconf ldap1 security rsa set --nss-cert-name "ldap1-2027"Restart ldap1 to pick up the NSS change:
dsctl ldap1 restartcertutil, pk12util, or offline dsctl tls commands edit NSS files on disk and do not synchronize the server's in-memory NSS state. Restart the instance after those changes.
After the instance is running, test both encrypted paths. Point LDAP clients at a current CA bundle you exported from NSS:
export LDAPTLS_CACERT=/root/example-ca-chain.pemTest LDAPS on port 636:
ldapsearch -x -H ldaps://ldap1.example.com:636 -b "" -s base "(objectClass=*)" namingContextsTest STARTTLS:
ldapsearch -x -ZZ -H ldap://ldap1.example.com:389 -b "" -s base "(objectClass=*)" namingContextsBoth searches should return the root DSE including namingContexts.
Verify the renewed certificate
Inspect the leaf certificate the listener presents:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -issuer -dates -serial -ext subjectAltNameValidate the complete chain:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com -showcerts -verify_return_error -CAfile /root/example-ca-chain.pem </dev/nullSample output near the end:
Verify return code: 0 (ok)Verify STARTTLS directly:
openssl s_client -starttls ldap -connect ldap1.example.com:389 -servername ldap1.example.com -verify_return_error -CAfile /root/example-ca-chain.pem </dev/nullSample output near the end:
Verify return code: 0 (ok)Compare with Directory Server's view:
dsctl ldap1 tls show-server-certOpen a new client connection after refresh-certs or the instance restart and confirm the serial number matches the renewed certificate. Also exercise:
- A normal LDAP user bind over LDAPS or STARTTLS
- Replication or chaining TLS settings if they pin certificates
- Monitoring probes and application LDAP clients that cache connections
Manage the NSS database password
dscreate stores the NSS password in two files for different purposes:
| File | Purpose |
|---|---|
pwdfile.txt |
Supplies the NSS database password to administrative tools |
pin.txt |
Supplies the token name and NSS password when Directory Server starts |
Both files live in the instance configuration directory:
/etc/dirsrv/slapd-ldap1/pwdfile.txt
/etc/dirsrv/slapd-ldap1/pin.txtpin.txt uses the token-and-password format:
Internal (Software) Token:NEW_NSS_PASSWORDConfirm that ownership, permissions, and SELinux types match a healthy instance created by the same 389 DS package. Do not recursively force one owner and group across the instance directory.
Change the NSS database password with certutil:
certutil -W -d /etc/dirsrv/slapd-ldap1 -f /etc/dirsrv/slapd-ldap1/pwdfile.txtcertutil prompts for the old and new passwords interactively. It changes the NSS database password; it does not rewrite pwdfile.txt or pin.txt automatically.
After a successful password change:
- Put the new password alone in
pwdfile.txt. - Update
pin.txtusingInternal (Software) Token:NEW_NSS_PASSWORD. - Preserve the existing ownership and mode of both files.
- Update secret-management or automation references.
- Restart the instance and verify that all NSS operations and TLS still work.
RHDS explicitly requires updating pin.txt when the NSS password changes.
Remove obsolete certificates safely
Before you delete a certificate:
- Confirm it is not the active nickname (
dsconf ldap1 security rsa get). - Confirm replication agreements, chaining, or client-auth settings do not reference it.
- Export a PKCS#12 backup when the private key might still be needed.
- Delete by exact nickname.
- Retest server startup and TLS.
Remove a server certificate nickname:
dsconf ldap1 security certificate del Server-CertSample output:
Successfully deleted certificateOnly remove the obsolete nickname after confirming the new certificate is active:
dsconf ldap1 security rsa getThat command should return nssslpersonalityssl: ldap1-2027 before you delete Server-Cert.
Or with dsctl while the instance is stopped. Stop the instance before offline NSS edits:
dsctl ldap1 stopRemove the obsolete nickname from the NSS database:
dsctl ldap1 tls remove-cert Server-CertStart the instance again so it reloads the trimmed certificate store:
dsctl ldap1 startDo not remove an issuing CA until every active server certificate has moved to a chain that no longer depends on it.
Recover from an expired certificate
Directory Server still starts
Import the renewed or replacement certificate, link it to the correct private key, set the active nickname, run dsconf config refresh-certs or restart according to your version, then verify LDAPS and STARTTLS from localhost before you reopen remote access.
Directory Server cannot provide LDAP TLS
Work locally on the host while the instance is stopped:
- Use
dsctlandcertutilagainst/etc/dirsrv/slapd-ldap1/ - Restore the configuration directory from your latest backup when the NSS database is corrupt
- Import a PKCS#12 bundle into a temporary NSS directory first when you want to validate contents before merging
- Confirm
pwdfile.txtandpin.txtstill unlockkey4.db - Set
nsSSLPersonalitySSLback to a nickname that has both certificate and private key
While the instance is stopped, validate the NSS contents locally. Display the active nickname certificate:
certutil -L -d /etc/dirsrv/slapd-ldap1 -n "ldap1-2027"List private keys in the NSS database:
certutil -K -d /etc/dirsrv/slapd-ldap1 -f /etc/dirsrv/slapd-ldap1/pwdfile.txtStart the instance only after those offline checks succeed:
dsctl ldap1 startThen test the listener:
openssl s_client -connect localhost:636 -servername ldap1.example.com -CAfile /root/example-ca-chain.pem -verify_return_error </dev/nullRestore certificates from backup
You can restore from:
- A
dsconf backup createordsctl db2bakarchive (remember thatconfig_files/is not restored automatically with the database) - A supplemental
tararchive of/etc/dirsrv/slapd-INSTANCE/ - A password-protected PKCS#12 export
Restore NSS files from config_files/
An RHDS backup stores NSS material under config_files/ in the backup directory. Set the backup path you verified earlier:
BACKUP_DIR="/var/lib/dirsrv/slapd-ldap1/bak/ldap1-BACKUP/config_files"Stop the instance before replacing NSS files on disk:
dsctl ldap1 stopPreserve the current files first so you can roll back if the restore fails:
mkdir -p /root/ldap1-current-nss
cp -a \
/etc/dirsrv/slapd-ldap1/cert9.db \
/etc/dirsrv/slapd-ldap1/key4.db \
/etc/dirsrv/slapd-ldap1/pin.txt \
/etc/dirsrv/slapd-ldap1/pwdfile.txt \
/root/ldap1-current-nss/Copy the backed-up NSS material into the live instance configuration directory:
cp -a \
"$BACKUP_DIR/cert9.db" \
"$BACKUP_DIR/key4.db" \
"$BACKUP_DIR/pin.txt" \
"$BACKUP_DIR/pwdfile.txt" \
/etc/dirsrv/slapd-ldap1/I'll restore SELinux file contexts on the replaced NSS files with restorecon; see Ansible SELinux file contexts for how labels are applied after copies or restores:
restorecon -Rv /etc/dirsrv/slapd-ldap1RHDS backs up configuration and certificate files together but requires administrators to restore selected files manually. This workflow restores NSS material only; it does not restore dse.ldif. The configured certificate nickname and the certificate present in NSS therefore need to remain consistent.
Before you start the instance, confirm that nsSSLPersonalitySSL matches a nickname in the restored NSS database. Read the configured active nickname from dse.ldif:
grep -i 'nssslpersonalityssl' /etc/dirsrv/slapd-ldap1/dse.ldifList the certificate nicknames present in the restored NSS database:
certutil -L -d /etc/dirsrv/slapd-ldap1Confirm that the nickname in nsSSLPersonalitySSL exists in the restored NSS database and has a matching private key. If it does not, either restore the matching dse.ldif from the same backup or, while the instance remains stopped, update nsSSLPersonalitySSL to a certificate nickname present in the restored database. Restoring the complete dse.ldif also rolls back unrelated instance configuration, so use it only when that full configuration rollback is intended.
List private keys in the restored database using the NSS password file:
certutil -K -d /etc/dirsrv/slapd-ldap1 -f /etc/dirsrv/slapd-ldap1/pwdfile.txtOnly start the instance after the certificate nickname and private key are both present:
dsctl ldap1 startRestore from a tar archive
For a configuration-directory restore, stop the instance, move the current directory aside, and extract the archive with ACLs, extended attributes, and SELinux labels preserved. Stop ldap1 before replacing its configuration directory:
dsctl ldap1 stopMove the broken configuration aside so you can extract the archive cleanly:
mv /etc/dirsrv/slapd-ldap1 /etc/dirsrv/slapd-ldap1.broken.$(date +%F)Extract the stopped-instance archive back into /etc/dirsrv:
tar --acls --xattrs --selinux -xzpf /root/slapd-ldap1-config-2026-07-16-0742.tar.gz -C /etc/dirsrvI'll run restorecon on the extracted configuration tree so file labels match policy:
restorecon -Rv /etc/dirsrv/slapd-ldap1Start the instance after the extract completes:
dsctl ldap1 startVerify sensitive files individually rather than applying a blanket chown. Check ownership with the chown command, file mode, and SELinux type on the NSS password files and databases:
ls -lZ \
/etc/dirsrv/slapd-ldap1/cert9.db \
/etc/dirsrv/slapd-ldap1/key4.db \
/etc/dirsrv/slapd-ldap1/pin.txt \
/etc/dirsrv/slapd-ldap1/pwdfile.txtConfirm that ownership, permissions, and SELinux types match a healthy instance created by the same 389 DS package. Do not recursively force one owner and group across the instance directory.
Output from this tested Rocky Linux package; other packages can differ:
-rw-------. 1 dirsrv dirsrv unconfined_u:object_r:dirsrv_config_t:s0 ... cert9.db
-rw-------. 1 dirsrv dirsrv unconfined_u:object_r:dirsrv_config_t:s0 ... key4.db
-rw-------. 1 dirsrv dirsrv unconfined_u:object_r:dirsrv_config_t:s0 ... pin.txt
-rw-------. 1 dirsrv dirsrv unconfined_u:object_r:dirsrv_config_t:s0 ... pwdfile.txtThen verify the active nickname and TLS listener. Confirm which certificate nickname Directory Server will use:
dsconf ldap1 security rsa getValidate the live LDAPS listener against your client CA bundle:
openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com -verify_return_error -CAfile /root/example-ca-chain.pem </dev/nullThe backup must belong to the same instance configuration unless you are following a documented migration procedure.
Do not overwrite a working NSS database without keeping a copy of the current directory.
Import a PKCS#12 bundle offline. pk12util modifies NSS files directly, so stop the instance first:
dsctl ldap1 stoppk12util -i imports into the existing NSS database rather than replacing the complete database. Inspect the bundle and current nicknames first. An existing certificate with the same nickname can cause an import conflict, and PKCS#12 import does not restore nsSSLPersonalitySSL automatically.
List the PKCS#12 contents before you import:
pk12util -l /root/ldap1-server-cert-backup.p12 -w /root/pk12-export.pwList current NSS nicknames so you can spot nickname conflicts:
certutil -L -d /etc/dirsrv/slapd-ldap1Import the PKCS#12 bundle into the instance NSS database:
pk12util -i /root/ldap1-server-cert-backup.p12 -d /etc/dirsrv/slapd-ldap1 -w /root/pk12-export.pw -k /etc/dirsrv/slapd-ldap1/pwdfile.txtBefore you start the instance, confirm that nsSSLPersonalitySSL matches a nickname in the NSS database and that the nickname has a matching private key. Read the configured active nickname:
grep -i 'nssslpersonalityssl' /etc/dirsrv/slapd-ldap1/dse.ldifList restored certificate nicknames:
certutil -L -d /etc/dirsrv/slapd-ldap1Confirm a private key is linked to the active nickname:
certutil -K -d /etc/dirsrv/slapd-ldap1 -f /etc/dirsrv/slapd-ldap1/pwdfile.txtOnly start the instance after the certificate nickname and private key are both present:
dsctl ldap1 startVerify nickname, trust flags, and dsconf ldap1 security rsa get before you expose the listener. config refresh-certs does not make a direct pk12util import safe online. The online-refresh design expects dsconf for changes made while the server is running.
Certificate renewal with attribute encryption
Follow the complete procedure in 389 Directory Server attribute encryption and the upstream section on updating TLS certificates used for attribute encryption before you change Server-Cert on an encrypted backend.
Monitor certificates before they expire
Track at least:
| Field | Example source |
|---|---|
| Nickname | dsconf ldap1 security rsa get |
| Subject and SAN | dsctl ldap1 tls show-server-cert |
| Issuing CA | dsconf ldap1 security certificate get "ldap1-2027" or the nickname returned by rsa get |
| Expiration | openssl x509 -checkend on live listener output |
| Renewal owner | Change-management ticket |
| Backup location | dsconf backup create archive and PKCS#12 path |
Test whether the certificate expires within 30 days. That pattern suits cron, systemd timers, or Nagios-compatible checks.
if ! openssl s_client -connect ldap1.example.com:636 -servername ldap1.example.com </dev/null 2>/dev/null | openssl x509 -checkend $((30 * 86400)) -noout; then echo "WARNING: ldap1 certificate expires within 30 days or could not be read"; exit 1; fiWhen the certificate is healthy, openssl x509 -checkend prints:
Certificate will not expireWhen the certificate is inside the window or unreadable, the script prints:
Certificate will expire
WARNING: ldap1 certificate expires within 30 days or could not be readThe exit status is non-zero when renewal action is required.
Troubleshoot certificate-management problems
| Symptom | Likely cause | Fix |
|---|---|---|
| Certificate imports but no private key is available | Signed cert does not match the CSR generated in NSS | Reissue from the same CSR public key; confirm with dsconf security key list |
| Private key does not match the certificate | Mixed PEM files from different CSRs or external keys | Import the matching pair with dsctl tls import-server-key-cert; restart afterward |
import-server-cert fails with SEC_ERROR_ADDING_CERT |
Server-Cert nickname already exists |
Use --nickname on current builds, or import online with dsconf security certificate add --name NEW_NICKNAME |
| Server presents the old certificate | Wrong active nickname, long-lived connections, or missing refresh-certs |
Check dsconf security rsa get; run dsconf config refresh-certs or restart |
| Certificate chain is incomplete | Missing intermediate CA in NSS | Import the missing intermediate and normally assign c,,; place C,, on the intended server-certificate trust anchor and add T only for client-authentication issuers |
| NSS password rejected | Wrong pwdfile.txt or pin.txt, permissions, or instance path |
Confirm -d /etc/dirsrv/slapd-INSTANCE; update both password files after certutil -W |
| Instance fails after NSS restore | Ownership, SELinux context, or password mismatch | Use tar --selinux and restorecon; verify individual file labels; confirm pwdfile.txt and pin.txt |
| LDAPS works but applications fail | Client trust store, SAN mismatch, or cached connections | Distribute exported CA PEM; align hostname with SAN; restart application pools |
| LDAPS fails after nickname switch | New nickname has no linked private key | Restore previous nickname; import cert that matches CSR key before retry |
refresh-certs not found |
Package reports 389 DS 3.2.0 but lacks the CLI subcommand | Run dsconf INSTANCE config --help; restart the instance after certificate changes when refresh-certs is absent |
What's Next
- FIPS mode — NSS FIPS enablement after certificate inventory
- Attribute encryption — encrypted attributes depend on TLS and NSS keys
- TLS ciphers and protocol versions — align cipher policy with renewed certificates
References
- Red Hat Directory Server 13 — Securing Red Hat Directory Server
- Red Hat Directory Server 13 — Backing up and restoring Red Hat Directory Server
- Red Hat Enterprise Linux 10.2 Release Notes — online TLS certificate refresh
- Red Hat Directory Server 13 — Updating TLS certificates used for attribute encryption
- 389 Directory Server — Online certificate refresh design
- 389 Directory Server 3.2.1 release notes
- 389 Directory Server — Howto: TLS/StartTLS
- NSS
certutildocumentation - NSS
pk12utildocumentation
Summary
- Inventory server and CA certificates, trust flags, and private-key linkage with
dsconfanddsctl. - Back up with
dsconf backup createand verifyconfig_files/containscert9.db,key4.db,pin.txt, andpwdfile.txt; supplement with PKCS#12 and stopped-instancetararchives. - Generate a CSR before expiry and verify SAN coverage before CA submission.
- Import the CA chain, then the signed leaf; confirm the private key is no longer
(orphan). - Set the active nickname with
dsconf security rsa set --nss-cert-name, then rundsconf config refresh-certswhen available or restart for offlinedsctlchanges. - Verify LDAPS, STARTTLS, and chain validation with
openssl s_client -verify_return_error. - Preserve recovery material, update both
pwdfile.txtandpin.txtafter NSS password changes, handle attribute encryption separately, and delete obsolete nicknames only after validation.

