Configure Read-only Databases and Instances in 389 Directory Server

Enable and disable backend and instance read-only mode in 389 Directory Server with dsconf, verify LDAP result code 53 on writes, recover from dse.ldif, and avoid replication mistakes.

Published

Updated

Read time 7 min read

Reviewed byDeepak Prasad

389 Directory Server read-only mode blocking LDAP writes with result code 53 while searches continue on userroot backend

Temporary read-only mode keeps 389 Directory Server online for searches while blocking adds, modifies, renames, and deletes. Use it during controlled maintenance. It is not a permanent access-control boundary.

Common reasons to enable read-only mode:

  • Freeze writes before backup export or validation
  • Block application updates during a schema or data migration window
  • Pause modifications on one suffix while another backend stays writable
  • Prevent accidental writes during manual consumer initialization planning

Before you start:

IMPORTANT
This guide covers backend-level and instance-level read-only mode with dsconf. It does not configure replication consumers or replace backup procedures in the backup and restore chapter. Read-only mode is not a substitute for a read-only replica.

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


Database read-only vs instance read-only

Mode Scope Configuration
Backend read-only One suffix/backend dsconf INSTANCE backend suffix set --enable-readonly BACKEND
Instance read-only Every database in the instance dsconf INSTANCE config replace nsslapd-readonly=on

Backend read-only blocks writes only under the selected suffix. Other backends in the same instance keep accepting modifications. Instance read-only applies to every database at once.

A replication consumer is a different design. The server holds a read-only copy of data and still receives updates from a supplier through replication agreements. Enabling read-only mode locally does not create that topology. It stops replication on the affected backend or instance.


Prepare the test environment

This lab uses instance ldap1, backend userroot, suffix dc=example,dc=com, and disposable test entry uid=user1,ou=people,dc=example,dc=com whose description attribute was initially absent. On an existing account, record and restore the original value instead of deleting the attribute during cleanup.

Confirm no suffix is under active replication before you test read-only mode on a production-like system:

bash
dsconf ldap1 replication list

Sample output:

output
There are no replicated suffixes

List backends and suffix DNs:

bash
dsconf ldap1 backend suffix list

Sample output:

output
dc=example,dc=com (userroot)

The backend name in dsconf commands is userroot (lowercase). Clients search using the suffix DN dc=example,dc=com.

Confirm the global instance flag is off before you begin:

bash
dsconf ldap1 config get nsslapd-readonly

Sample output:

output
nsslapd-readonly: off

Make one backend read-only

Enable read-only mode on userroot:

bash
dsconf ldap1 backend suffix set --enable-readonly userroot

Sample output:

output
The backend configuration was successfully updated

Verify the backend flag:

bash
dsconf ldap1 backend suffix get userroot

Sample output (trimmed):

output
nsslapd-readonly: on
nsslapd-suffix: dc=example,dc=com

Only userroot is read-only; a second backend in the same instance would still accept writes until you enable read-only on that backend as well.


Test read and write operations

Searches against the read-only backend should still succeed with ldapsearch:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=user1,ou=people,dc=example,dc=com" -s base dn

Sample output:

output
dn: uid=user1,ou=people,dc=example,dc=com

Attempt a modification on the same backend with ldapmodify to confirm writes are rejected:

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: readonly backend test
EOF

Sample output:

output
ldap_modify: Server is unwilling to perform (53)
	additional info: database is read-only
modifying entry "uid=user1,ou=people,dc=example,dc=com"

Result code 53 with database is read-only confirms backend read-only mode is active. That is not an ACI denial.


Restore the backend to read-write mode

Disable backend read-only mode:

bash
dsconf ldap1 backend suffix set --disable-readonly userroot

Sample output:

output
The backend configuration was successfully updated

Repeat the same modification to confirm writes work again:

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: rw restored
EOF

The command completes without result code 53, which means the backend accepts writes again.


Make the entire instance read-only

When every database in the instance must reject writes, I'll set the global flag:

Instance read-only mode blocks writes to directory databases, but it does not make cn=config immutable. Directory Server configuration can still be changed while the instance is running. You can run dsconf to update settings even though RHDS documents that the instance cannot be restarted in this state.

bash
dsconf ldap1 config replace nsslapd-readonly=on

Sample output:

output
Successfully replaced value(s) for 'nsslapd-readonly': 'on'

Confirm the setting:

bash
dsconf ldap1 config get nsslapd-readonly

Sample output:

output
nsslapd-readonly: on

Search still works at the suffix root:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "dc=example,dc=com" -s base "(objectClass=*)" dn

Sample output:

output
dn: dc=example,dc=com

Attempt a write while the instance is read-only:

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: instance readonly test
EOF

Sample output:

output
ldap_modify: Server is unwilling to perform (53)
	additional info: Server is read-only
modifying entry "uid=user1,ou=people,dc=example,dc=com"

Instance read-only reports Server is read-only rather than database is read-only.

IMPORTANT
Disable instance read-only mode before you stop the server. If nsslapd-readonly is on when the instance shuts down, dsctl ldap1 start fails until you edit dse.ldif manually. Do not use dsctl restart as a shortcut while the instance is globally read-only.

Restore the instance to read-write mode

Return the instance to normal operation:

bash
dsconf ldap1 config replace nsslapd-readonly=off

Sample output:

output
Successfully replaced value(s) for 'nsslapd-readonly': 'off'

Verify writes succeed:

bash
ldapmodify -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=user1,ou=people,dc=example,dc=com
changetype: modify
replace: description
description: instance rw restored
EOF

The modify completes without error when global read-only mode is cleared.


Recover if the read-only instance was stopped

If the instance was stopped while nsslapd-readonly was on, online dsconf cannot clear the flag because the server is not running. Edit the on-disk configuration instead.

Back up the file first:

bash
cp -a /etc/dirsrv/slapd-ldap1/dse.ldif /etc/dirsrv/slapd-ldap1/dse.ldif.before-readonly-fix

Locate nsslapd-readonly under the cn=config entry in the stopped instance:

bash
grep -n 'nsslapd-readonly' /etc/dirsrv/slapd-ldap1/dse.ldif | head -3

Sample output:

output
41:nsslapd-readonly: on

Edit /etc/dirsrv/slapd-ldap1/dse.ldif with your preferred text editor while the instance is stopped and change that line to nsslapd-readonly: off under dn: cn=config. An instance stopped in global read-only mode cannot start again until this value is off.

Start the instance:

bash
dsctl ldap1 start

Confirm the flag and a test write:

bash
dsconf ldap1 config get nsslapd-readonly

Sample output:

output
nsslapd-readonly: off

Read-only mode and replication

Do not enable backend or instance read-only mode on an active replicated database. Red Hat documents that read-only mode disables replication on that backend. It does not convert the server into a normal supplier and consumer pair.

Use the replication workflow when you need a read-only copy that still receives updates from a supplier:

If replication stops unexpectedly after read-only mode was enabled, disable read-only on the supplier backend, confirm that replication remains enabled with dsconf ldap1 replication list, list agreements with dsconf ldap1 repl-agmt list --suffix="dc=example,dc=com", and inspect each agreement with dsconf ldap1 repl-agmt status --suffix="dc=example,dc=com" AGREEMENT_NAME before you re-enable updates.


Troubleshoot read-only mode

Symptom Likely cause Fix
Writes still succeed Read-only applied to wrong backend, or only instance flag checked Run dsconf ldap1 backend suffix get BACKEND and dsconf ldap1 config get nsslapd-readonly; enable the correct scope
Only one suffix rejects writes Backend read-only, not instance read-only Expected for --enable-readonly on one backend; use nsslapd-readonly=on only when every database must block writes
LDAP result code 53 on modify Read-only mode active Confirm backend or instance flag before debugging ACIs
database is read-only vs Server is read-only Backend-level vs instance-level flag Match the message to backend suffix set or nsslapd-readonly
dsctl start fails after maintenance Instance stopped while nsslapd-readonly was on Edit /etc/dirsrv/slapd-INSTANCE/dse.ldif, set nsslapd-readonly: off under cn=config, then start
Replication stopped Read-only enabled on a replicated backend Disable read-only mode; use dsconf ldap1 replication list, repl-agmt list, and repl-agmt status to verify agreements

Summary

  1. Use backend read-only mode (--enable-readonly) to freeze writes on one suffix.
  2. Use instance read-only mode (nsslapd-readonly=on) only when every database must reject writes.
  3. Verify both successful searches and rejected modifications. Expect LDAP result code 53.
  4. Disable instance read-only before stopping the server; otherwise edit dse.ldif to recover.
  5. Do not use read-only mode as a replacement for a replication consumer.

What's Next


References


Frequently Asked Questions

1. What is the difference between backend read-only and instance read-only in 389 Directory Server?

Backend read-only applies to one suffix through dsconf backend suffix set --enable-readonly. Instance read-only sets nsslapd-readonly=on in cn=config and blocks writes to every database in the instance.

2. Is read-only mode the same as a replication consumer?

No. A replication consumer receives updates from a supplier through replication agreements. Read-only mode rejects local writes and disables replication on that backend or instance—it does not make the server a normal consumer replica.

3. What LDAP result code appears when a write hits read-only mode?

Add, modify, rename, and delete operations return LDAP result code 53 (unwilling to perform). Backend read-only usually reports database is read-only; instance read-only reports Server is read-only.

4. Why must I disable instance read-only before stopping the server?

An instance stopped while nsslapd-readonly is on cannot be started again with dsctl until you edit /etc/dirsrv/slapd-INSTANCE/dse.ldif and set nsslapd-readonly to off under cn=config.

5. Can I enable read-only mode on a replicated database?

Do not enable backend or instance read-only on an active replicated database. Red Hat documents that read-only mode disables replication rather than converting the server into a consumer replica.
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 …