Assign Unique UID and GID Numbers with the 389 DS DNA Plugin

Tested on Rocky Linux 10.2 (Red Quartz)
Package 389-ds-base 3.2.0-8.el10_2
Applies to RHEL, Rocky Linux, AlmaLinux, Oracle Linux, CentOS Stream, Fedora
Privilege sudo or root
Scope Configure the 389 Directory Server Distributed Numeric Assignment plug-in for automatic uidNumber and gidNumber allocation, magic regeneration values, separate or shared ranges, multi-supplier range transfer, monitoring, and troubleshooting.
Related guides Install 389 Directory Server
Manage users and groups
dsconf commands
dsidm commands

POSIX users and groups need numeric uidNumber and gidNumber values. In a growing directory, tracking the next free ID by hand does not scale, and overlapping ranges between suppliers can create collisions. The Distributed Numeric Assignment (DNA) plug-in assigns numbers from administrator-defined ranges when qualifying entries are added or modified.

This guide covers the complete automatic numeric-value allocation workflow in 389 Directory Server:

  • Assigning uidNumber and gidNumber
  • Scope and entry filters
  • Starting and maximum values
  • Magic regeneration values
  • Managing one or multiple attributes
  • Assigning the same or different values to multiple attributes
  • Equality indexes with integer ordering matching rules
  • Range exhaustion
  • Multi-supplier ranges
  • Shared range configuration
  • Automatic range transfer
  • Monitoring and troubleshooting

The DNA plug-in assigns numbers from configured ranges. It does not guarantee uniqueness for manually supplied values. Administrators can still add an explicit number, and the plug-in does not reject it merely because another entry already has that value. Use Attribute Uniqueness where all manual and generated values must be checked.

Before you start:

IMPORTANT
This guide configures automatic numeric ID allocation only. It does not cover POSIX user and group creation (users and groups), rejecting manually supplied duplicates (Attribute Uniqueness), bulk LDIF import plug-in behavior, or full multi-supplier replication agreement configuration.

How the DNA plug-in works

When a qualifying entry is added or modified, DNA generates a number when a managed attribute equals dnaMagicRegen. When the configuration manages only one attribute, DNA can also generate the value when that attribute is omitted. For configurations managing multiple attributes, include the magic value on each attribute that should receive a generated number.

WARNING
Configure dnaMagicRegen when clients may submit explicit numeric values. Without a magic regeneration value, DNA can replace values supplied for managed attributes. With dnaMagicRegen: -1, normal explicit values are preserved and only -1 triggers regeneration.
text
New posixAccount entry
        |
        | uidNumber equals dnaMagicRegen
        | or omitted when only one attribute is managed
        v
DNA plug-in checks:
scope + LDAP filter
        |
        v
Assigns the next number from the configured range
        |
        v
Increments dnaNextValue
Setting Purpose
dnaType Attribute or attributes whose values are generated
dnaScope Directory subtree managed by the configuration
dnaFilter Entry types eligible for number assignment
dnaNextValue Next number available for assignment
dnaMaxValue Upper limit of the current range
dnaMagicRegen Placeholder value that triggers number generation
dnaNextRange Reserve range used after the current range
dnaSharedCfgDN Replicated location containing supplier range information
dnaThreshold Remaining-value threshold that triggers a range request
dnaRangeRequestTimeout Time to wait for a supplier to provide a range

Compare DNA with Attribute Uniqueness

Feature DNA plug-in Attribute Uniqueness plug-in
Generates values Yes No
Manages numeric ranges Yes No
Rejects manually entered duplicates No Yes
Coordinates supplier ranges Yes No
Works with nonnumeric attributes Limited by attribute syntax Yes

The plug-ins complement each other:

text
DNA generates uidNumber values
        +
Attribute Uniqueness rejects manually introduced duplicates

Prepare the directory and POSIX entries

The lab tree under dc=example,dc=com uses dedicated DNA test users so the guide does not disturb existing course accounts:

text
dc=example,dc=com
├── ou=People
│   └── posixAccount users
└── ou=Groups
    └── posixGroup groups

Planned numeric range for the primary UID lab:

text
Initial number: 10000
Maximum number: 19999
Magic value: -1

The runnable single-server lab manages:

text
uidNumber

Later sections explain alternative configurations that manage gidNumber separately or manage both uidNumber and gidNumber from one shared pool.

The selected range must not overlap:

  • Existing LDAP values in the suffix
  • Local operating-system accounts on client hosts
  • Other identity providers
  • Ranges assigned to other suppliers

Do not enable DNA until the proposed range is confirmed safe.


Audit existing UID and GID values

Search current POSIX users under ou=People:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "ou=People,dc=example,dc=com" "(uidNumber=*)" dn uid uidNumber gidNumber

Sample output:

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

dn: uid=user2,ou=people,dc=example,dc=com
uid: user2
uidNumber: 3002
gidNumber: 3002

Search current groups under ou=Groups:

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

On this lab host the group search returned no gidNumber values. The displayed user IDs are well below the proposed DNA range beginning at 10000.

Before you enable DNA, identify:

  • The highest existing UID and GID
  • Duplicate values
  • Values inside the proposed DNA range
  • Ranges reserved by another supplier or identity system

Create required indexes

The DNA plug-in performs sorted internal searches when checking available values. Every managed attribute needs an equality index configured with its appropriate ordering matching rule in the backend that contains the scoped entries.

Confirm the uidNumber index on userroot:

bash
dsconf ldap1 backend index get userroot --attr uidNumber

Sample output before adding the ordering rule:

output
dn: cn=uidnumber,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
cn: uidnumber
nsIndexType: eq

If the index is missing, create equality indexing with integerOrderingMatch and reindex:

bash
dsconf ldap1 backend index add --attr uidNumber --index-type eq --matching-rule integerOrderingMatch --reindex userroot

When an equality index already exists but lacks the ordering rule, update the index entry and reindex it:

bash
ldapmodify -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd-ldap1.socket <<'EOF'
dn: cn=uidnumber,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
changetype: modify
replace: nsMatchingRule
nsMatchingRule: integerOrderingMatch
EOF

Sample output:

output
modifying entry "cn=uidnumber,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config"

Rebuild the index:

bash
dsconf ldap1 backend index reindex --attr uidNumber userroot

Sample output:

output
Index task index_attrs_2026-07-17T22:41:28.732248 completed successfully
Successfully reindexed database

Verify the active index:

bash
dsconf ldap1 backend index get userroot --attr uidNumber

Sample output:

output
dn: cn=uidnumber,cn=index,cn=userroot,cn=ldbm database,cn=plugins,cn=config
cn: uidnumber
nsIndexType: eq
nsMatchingRule: integerOrderingMatch

Repeat the same check and update for gidNumber. Full index creation and reindexing steps are covered in index design and maintenance.

Keep each DNA configuration scope within one database backend. The plug-in is not designed to manage one range across multiple backends.


Check the current DNA plug-in configuration

Review the plug-in state:

bash
dsconf ldap1 plugin dna show

Sample output:

output
dn: cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config
cn: Distributed Numeric Assignment Plugin
nsslapd-pluginEnabled: off
nsslapd-pluginInitfunc: dna_init
nsslapd-pluginPath: libdna-plugin
nsslapd-pluginType: bepreoperation

List existing DNA configuration entries:

bash
ldapsearch -LLL -Y EXTERNAL -H ldapi://%2Fvar%2Frun%2Fslapd-ldap1.socket -b "cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config" "(objectClass=dnaPluginConfig)" cn

On a fresh instance this search returns no configuration entries. If the search finds an existing configuration, inspect it using the returned cn value:

bash
dsconf ldap1 plugin dna config "EXISTING_CONFIG_NAME" show

Record any existing configurations before you add a new one.

Review these settings before you enable DNA:

output
dnaType
dnaFilter
dnaScope
dnaNextValue
dnaMaxValue
dnaMagicRegen
dnaNextRange
dnaSharedCfgDN
dnaThreshold

Confirm option names on your installed version:

bash
dsconf ldap1 plugin dna config "Account UIDs" add --help

Configure automatic uidNumber assignment

Create a configuration for POSIX users under ou=People:

bash
dsconf ldap1 plugin dna config "Account UIDs" add --type uidNumber --filter "(objectClass=posixAccount)" --scope "ou=People,dc=example,dc=com" --next-value 10000 --max-value 19999 --magic-regen -1

Sample output:

output
Successfully created the cn=Account UIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config

Enable the plug-in:

bash
dsconf ldap1 plugin dna enable

Sample output:

output
Enabled plugin 'Distributed Numeric Assignment Plugin'

Restart the instance so the plug-in loads:

bash
dsctl ldap1 restart

Confirm the instance is running:

bash
dsctl ldap1 status

Sample output:

output
Instance "ldap1" is running

Verify the configuration:

bash
dsconf ldap1 plugin dna config "Account UIDs" show

Sample output:

output
cn: Account UIDs
dnaFilter: (objectClass=posixAccount)
dnaMagicRegen: -1
dnaMaxValue: 19999
dnaNextValue: 10000
dnaScope: ou=People,dc=example,dc=com
dnaType: uidNumber

The dnaNextValue: 10000 line shows the next UID waiting to be assigned.


Trigger assignment with a magic value

Save the following as /tmp/dna-test1.ldif:

ldif
dn: uid=dna-test1,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: dna-test1
cn: DNA Test One
sn: One
homeDirectory: /home/dna-test1
uidNumber: -1
gidNumber: 3001

Add the entry:

bash
ldapadd -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/dna-test1.ldif

Sample output:

output
adding new entry "uid=dna-test1,ou=people,dc=example,dc=com"

Verify the assigned number:

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

Sample output:

output
dn: uid=dna-test1,ou=people,dc=example,dc=com
uidNumber: 10000
gidNumber: 3001

DNA replaced the magic value with 10000. The magic value must sit outside the generated range so it cannot be assigned as a normal ID.

Check that dnaNextValue advanced:

bash
dsconf ldap1 plugin dna config "Account UIDs" show | grep dnaNextValue

Sample output:

output
dnaNextValue: 10001

Assign a number when the attribute is missing

When the DNA configuration manages only one attribute, you can omit that attribute from a qualifying posixAccount entry. DNA assigns the next value during the add operation. This does not apply when the configuration manages multiple attributes; in that case supply the magic value on each attribute that should be generated.

bash
ldapadd -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=dna-omit,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: dna-omit
cn: DNA Omit Test
sn: Omit
homeDirectory: /home/dna-omit
gidNumber: 3001
EOF

Sample output:

output
adding new entry "uid=dna-omit,ou=people,dc=example,dc=com"
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=dna-omit,ou=people,dc=example,dc=com" -s base uidNumber

Sample output:

output
dn: uid=dna-omit,ou=people,dc=example,dc=com
uidNumber: 10001

Explicitly using the magic value in bulk LDIF templates is usually clearer because it makes the intended DNA behavior visible to operators reviewing the file.


Assign uidNumber and gidNumber from one shared range

Some deployments use one numeric namespace for automatically generated user and group IDs. Configure both managed attributes in one DNA configuration entry:

output
dsconf ldap1 plugin dna config "POSIX IDs" add \
  --type uidNumber gidNumber \
  --filter "(|(objectClass=posixAccount)(objectClass=posixGroup))" \
  --scope "dc=example,dc=com" \
  --next-value 10000 \
  --max-value 19999 \
  --magic-regen -1

Do not run this on the same server as a separate Account UIDs configuration that already manages uidNumber. Use one design per attribute namespace.

When both attributes are requested in one operation with the magic value:

ldif
uidNumber: -1
gidNumber: -1

the plug-in can assign the same generated number to both attributes on that entry.

IMPORTANT
A shared DNA range does not automatically create a private group or copy a user's uidNumber to the gidNumber of a separate posixGroup entry. Provisioning a matching private group requires a separate workflow, such as the Managed Entries plug-in, that reads the assigned user UID and explicitly uses that value for the group's GID.

Use cases:

  • A posixAccount entry whose uidNumber and primary gidNumber should have the same value
  • One generated number pool shared by uidNumber and gidNumber
  • Preventing automatically generated user UIDs from overlapping automatically generated group GIDs

Assign different values with a multi-attribute configuration

This behaviour applies only when one active DNA configuration manages both uidNumber and gidNumber. It does not work with the earlier Account UIDs configuration, which manages only uidNumber.

When multiple managed attributes are supplied in one operation, the plug-in can assign the same generated number to all of them. To allocate different numbers from the same range, trigger DNA separately for each attribute in separate modify operations.

First modify uidNumber with the magic value. Then modify gidNumber with the magic value in a second request. After both operations complete, verify the result:

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

Example structure when separate regeneration requests consume separate values from the range:

output
dn: uid=dna-test1,ou=people,dc=example,dc=com
uidNumber: 10002
gidNumber: 10003

DNA can assign one generated value to multiple requested attributes in one operation, or consume separate values when regeneration occurs in separate operations.


Configure separate UID and GID ranges

An alternative design keeps user and group namespaces independent:

text
Account UIDs:
10000–19999

Group GIDs:
20000–29999

Create two DNA configuration entries:

text
Account UIDs → uidNumber → posixAccount → ou=People
Group GIDs   → gidNumber → posixGroup   → ou=Groups

Example group configuration:

bash
dsconf ldap1 plugin dna config "Group GIDs" add --type gidNumber --filter "(objectClass=posixGroup)" --scope "ou=Groups,dc=example,dc=com" --next-value 20000 --max-value 29999 --magic-regen -1

Sample output:

output
Successfully created the cn=Group GIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config

Separate ranges are preferable when:

  • Users and groups use independently managed namespaces
  • Existing GIDs already occupy a different range
  • Applications require clear separation
  • Private-user groups are not used

Compare the shared-pool and separate-range designs before you choose one for production.

Design Best when
One shared UID/GID pool Automatically generated user and group IDs must never overlap
Separate UID and GID pools Users and groups have independent namespaces or existing range requirements
Matching private-user group Provisioning explicitly copies the user UID to the separate group GID

Understand explicitly supplied values

Add an entry with an explicit UID inside the DNA range:

bash
ldapadd -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw <<'EOF'
dn: uid=dna-explicit,ou=people,dc=example,dc=com
objectClass: top
objectClass: person
objectClass: organizationalPerson
objectClass: inetOrgPerson
objectClass: posixAccount
uid: dna-explicit
cn: DNA Explicit
sn: Explicit
homeDirectory: /home/dna-explicit
uidNumber: 15000
gidNumber: 3001
EOF

Sample output:

output
adding new entry "uid=dna-explicit,ou=people,dc=example,dc=com"
bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "uid=dna-explicit,ou=people,dc=example,dc=com" -s base uidNumber

Sample output:

output
uidNumber: 15000

Because this configuration defines dnaMagicRegen: -1, DNA preserves 15000. Without a configured magic value, explicitly supplied managed values can be replaced. DNA also does not verify that 15000 is unused. A manually assigned number can collide with a generated or existing value. Use Attribute Uniqueness when duplicate rejection is required.


Monitor the current range

Inspect the active configuration:

bash
dsconf ldap1 plugin dna config "Account UIDs" show

Sample output:

output
cn: Account UIDs
dnaFilter: (objectClass=posixAccount)
dnaMagicRegen: -1
dnaMaxValue: 19999
dnaNextValue: 10002
dnaScope: ou=People,dc=example,dc=com
dnaType: uidNumber

With dnaMaxValue: 19999 and dnaNextValue: 10002, the remaining values in the current range are:

output
19999 - 10002 + 1 = 9998

Monitor:

text
dnaNextValue
dnaMaxValue
dnaNextRange
dnaThreshold

Estimate remaining values in the current range:

text
Remaining current values =
dnaMaxValue - dnaNextValue + 1

In a multi-supplier deployment, also review the shared range entries:

text
dnaHostname
dnaPortNum
dnaSecurePortNum
dnaRemainingValues

Monitor remaining capacity before the range reaches the configured threshold.


Handle range exhaustion on one server

On a single supplier, number assignment succeeds until dnaMaxValue. When no next range is available, new qualifying add or modify operations fail. Existing entries remain unchanged.

Before you assign another range:

  1. Audit existing values.
  2. Check every supplier's range.
  3. Confirm the new range is unused.
  4. Back up the DNA configuration.
  5. Add or update dnaNextRange.
  6. Test with a new entry.

Never reset dnaNextValue to a lower value merely to make assignments resume.


Configure DNA in a multi-supplier topology

Before you split the lab into two suppliers, remove the temporary explicit-value test entry:

bash
ldapdelete -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw "uid=dna-explicit,ou=people,dc=example,dc=com"

That frees 15000 for Supplier 2's starting range. In an existing environment, audit the complete proposed range instead of deleting production entries.

Verify that 15000 is free:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "dc=example,dc=com" "(|(uidNumber=15000)(gidNumber=15000))" dn uidNumber gidNumber

A successful empty search prints no entries.

Each writable supplier needs:

  • A local DNA configuration
  • A non-overlapping active range
  • The same managed attributes, scope, and filter
  • Access to a shared configuration entry
  • Replication authentication for range requests

The DNA configuration under cn=plugins,cn=config is local to each supplier and must be created separately. The shared range container belongs in a replicated data suffix so every participating supplier receives the shared range records. DNA suppliers need non-overlapping local ranges and replicated shared range information.

Example layout:

text
Supplier 1:
Current range 10000–14999

Supplier 2:
Current range 15000–19999

Shared range information:
Stored inside a replicated suffix

Directory Server tracks each supplier's range in replicated shared entries so one supplier can request values from another when its local range is nearly exhausted.

Create the shared range configuration

Save the following as /tmp/dna-ranges.ldif:

ldif
dn: ou=Ranges,dc=example,dc=com
objectClass: top
objectClass: organizationalUnit
objectClass: extensibleObject
ou: Ranges

dn: cn=Account UIDs,ou=Ranges,dc=example,dc=com
objectClass: top
objectClass: extensibleObject
cn: Account UIDs
bash
ldapadd -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -f /tmp/dna-ranges.ldif

Sample output:

output
adding new entry "ou=Ranges,dc=example,dc=com"

adding new entry "cn=Account UIDs,ou=Ranges,dc=example,dc=com"

Configure the first supplier with shared-range settings. Confirm the current range before you lower the maximum:

bash
dsconf ldap1 plugin dna config "Account UIDs" show

Only lower --max-value if dnaNextValue has not already passed the new maximum. Then apply the Supplier 1 multi-supplier settings:

bash
dsconf ldap1 plugin dna config "Account UIDs" set --max-value 14999 --shared-config-entry "cn=Account UIDs,ou=Ranges,dc=example,dc=com" --threshold 500 --range-request-timeout 60

Sample output:

output
Successfully changed the cn=Account UIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config

Verify Supplier 1 after lowering the maximum:

bash
dsconf ldap1 plugin dna config "Account UIDs" show

Sample output:

output
dnaMaxValue: 14999
dnaSharedCfgDN: cn=Account UIDs,ou=Ranges,dc=example,dc=com
dnaThreshold: 500
dnaRangeRequestTimeout: 60

Create the Supplier 2 configuration with a non-overlapping range:

bash
dsconf ldap2 plugin dna config "Account UIDs" add --type uidNumber --filter "(objectClass=posixAccount)" --scope "ou=People,dc=example,dc=com" --next-value 15000 --max-value 19999 --magic-regen -1 --shared-config-entry "cn=Account UIDs,ou=Ranges,dc=example,dc=com" --threshold 500 --range-request-timeout 60

Enable and verify Supplier 2:

bash
dsconf ldap2 plugin dna enable
bash
dsctl ldap2 restart
bash
dsctl ldap2 status

Sample output:

output
Instance "ldap2" is running

Verify the Supplier 2 configuration:

bash
dsconf ldap2 plugin dna config "Account UIDs" show

When ldap2 is running with the same suffix and replicated shared range container, the output should show a non-overlapping range such as:

output
dnaMaxValue: 19999
dnaNextValue: 15000
dnaSharedCfgDN: cn=Account UIDs,ou=Ranges,dc=example,dc=com

The shared DN must live under a suffix replicated to every participating supplier.

After both suppliers are configured, verify that each server created its automatically maintained dnaSharedConfig child entry:

bash
ldapsearch -LLL -x -H ldap://127.0.0.1:389 -D "cn=Directory Manager" -y /root/dm.pw -b "cn=Account UIDs,ou=Ranges,dc=example,dc=com" "(objectClass=dnaSharedConfig)" dnaHostname dnaPortNum dnaSecurePortNum dnaRemainingValues

Expected structure:

output
dn: dnaHostname=ldap1.example.com+dnaPortNum=389,cn=Account UIDs,ou=Ranges,dc=example,dc=com
dnaHostname: ldap1.example.com
dnaPortNum: 389
dnaSecurePortNum: 636
dnaRemainingValues: ...

dn: dnaHostname=ldap2.example.com+dnaPortNum=389,cn=Account UIDs,ou=Ranges,dc=example,dc=com
dnaHostname: ldap2.example.com
dnaPortNum: 389
dnaSecurePortNum: 636
dnaRemainingValues: ...

Use the actual ports from your topology. Each supplier automatically maintains a child entry under dnaSharedCfgDN, and these entries are what other suppliers use to discover donors and their available capacity.

Understand automatic range transfer

output
Supplier 1 approaches dnaThreshold
        |
        v
Reads replicated shared range entries
        |
        v
Contacts another supplier
        |
        v
Requests part of its remaining range
        |
        v
Transferred range becomes Supplier 1's next available range
Setting Purpose
dnaThreshold Starts the range-request process before exhaustion
dnaRangeRequestTimeout Limits how long one supplier is contacted
dnaSharedCfgDN Provides supplier and remaining-range information
dnaNextRange Stores the transferred reserve range

DNA range requests use the connection and authentication information associated with replication between the participating suppliers. The requesting supplier must be recognized and authorized by the donor. When the replication agreement uses TLS or certificate authentication, the DNA range request follows that security design. If range transfer fails, verify the replication bind identity, credentials, TLS trust, supplier hostname and ports, and the replicated shared entries.

A donor transfers values from the upper end of its available range. It does not donate its complete remaining range. It retains enough values to continue local allocation, and transfer size is constrained by the available range and threshold.

Use TLS-protected server-to-server connections where your deployment requires them.

Test range transfer safely

Use small lab ranges on two suppliers, for example:

text
Supplier 1: 10000–10004
Supplier 2: 20000–20020
Threshold: 2

Create enough users through Supplier 1 to approach the threshold, then verify:

  • Supplier 1 sends a range request
  • Supplier 2's remaining range decreases
  • Supplier 1 receives a next range
  • No duplicate values are generated
  • Shared configuration entries update on both suppliers

Do not force a production range to exhaustion merely to demonstrate the feature.

Add or remove a supplier

Before enabling DNA on a new writable supplier:

  1. Create a local configuration matching the topology.
  2. Assign a non-overlapping initial range.
  3. Confirm the shared configuration has replicated.
  4. Verify connection details and credentials.
  5. Enable the plug-in.
  6. Test one user creation through the new supplier.
  7. Confirm the generated value does not overlap other suppliers.

Before decommissioning a supplier, record its active and next ranges, prevent new writes, and confirm whether unused values will be transferred or recovered manually.


Performance and indexing considerations

DNA uses internal searches to identify available values, so unindexed managed attributes increase add and modify latency.

Monitor:

  • Add and modify latency
  • Unindexed search messages in the access log
  • Size of the managed subtree
  • Number of managed attributes
  • Range-request delays
  • Supplier connectivity
  • Write activity during bulk imports

Keep DNA scopes within one backend.


Troubleshoot the DNA plug-in

Symptom Likely cause Fix
uidNumber is not generated Plug-in disabled, scope or filter mismatch, magic value not supplied when required, single-attribute omission used with multi-attribute config, range exhausted Enable plug-in, restart instance, confirm scope, filter, magic value, managed-attribute count, and remaining range
Magic value remains unchanged Supplied value does not exactly match dnaMagicRegen Align the client value with the configured magic regeneration value
Explicit value replaced unexpectedly dnaMagicRegen absent or overlaps valid IDs Use a dedicated magic value outside every active range
Assignment fails after dnaMaxValue No dnaNextRange or no transferable supplier range Add next range or fix shared configuration and supplier connectivity
Range transfer times out Hostname, port, TLS, bind credentials, or replication delay Review dnaRangeRequestTimeout, shared entry replication, and network path
Results differ across suppliers Mismatched scope, filter, range, or magic value Compare full configuration and replication status on every supplier
User UID collides with a group GID Separate namespaces without planning Use one shared UID/GID pool or separate ranges deliberately
Bulk import does not assign IDs Offline database import does not run normal add-operation plug-ins Include final numeric values in imported LDIF, or perform subsequent LDAP add or modify operations that trigger DNA

Disable or remove a DNA configuration

Before disabling DNA:

  1. Record dnaNextValue, dnaMaxValue, and dnaNextRange.
  2. Stop automated user provisioning that depends on DNA.
  3. Confirm how new entries will receive numeric IDs.
  4. Disable the plug-in or delete only the intended configuration.
  5. Test a controlled user add.
  6. Preserve range records for possible rollback.

Disable the plug-in:

bash
dsconf ldap1 plugin dna disable

Sample output:

output
Disabled plugin 'Distributed Numeric Assignment Plugin'

Restart the instance:

bash
dsctl ldap1 restart
bash
dsctl ldap1 status

Sample output:

output
Instance "ldap1" is running

Disabling the plug-in retains its configuration and current range state.

Delete one configuration entry:

bash
dsconf ldap1 plugin dna config "Account UIDs" delete

Sample output:

output
Successfully deleted the cn=Account UIDs,cn=Distributed Numeric Assignment Plugin,cn=plugins,cn=config

Deleting a configuration removes that allocation definition. Neither disabling the plug-in nor deleting a configuration removes numeric values already assigned to directory entries.

Do not reuse an abandoned range elsewhere until every assigned value has been audited.


What's next

After you complete this guide, continue with:

Summary

  1. Audit existing UID and GID values.
  2. Create equality indexes with integer ordering matching rules.
  3. Define the managed attribute, scope, filter, and range.
  4. Use a magic value outside the valid range.
  5. Test automatic assignment on new and existing entries.
  6. Decide whether UID and GID use one shared pool or separate ranges.
  7. Monitor the next and maximum values.
  8. Use shared range configuration for multiple writable suppliers.
  9. Test range transfer before production exhaustion.
  10. Pair DNA with Attribute Uniqueness when manual duplicates must be rejected.

A basic single-server configuration requires the managed attribute, filter, scope, and next value. Multi-supplier configurations add maximum values, shared configuration, thresholds, request timeouts, and optionally a reserve range.


References


Frequently Asked Questions

1. What is the difference between the DNA plug-in and Attribute Uniqueness?

The DNA plug-in generates numeric values from configured ranges when a managed attribute equals dnaMagicRegen, or when a single-attribute configuration omits that attribute. Attribute Uniqueness rejects duplicate values that clients supply manually. DNA does not guarantee uniqueness for explicitly entered numbers. Use both when you want automatic allocation and duplicate rejection.

2. What magic value should I use for uidNumber?

Use a value clearly outside every active DNA range, such as -1. Avoid 0 when your directory or POSIX clients may treat it as a valid or special ID. The magic value must exactly match dnaMagicRegen to trigger regeneration.

3. Can DNA assign the same uidNumber and gidNumber automatically?

Yes. Configure one DNA configuration entry with both uidNumber and gidNumber in dnaType and supply the magic value for both attributes in the same add or modify operation. The plug-in can assign the same generated number to every managed attribute requested in that operation.

4. Why was uidNumber not assigned on my new user?

Check that the plug-in is enabled, the entry is inside dnaScope, the entry matches dnaFilter, and the current range has values available. When dnaMagicRegen is configured, the attribute must equal that value. Omitting the attribute triggers assignment only when the DNA configuration manages a single attribute.

5. Does DNA prevent duplicate UID numbers?

No. DNA allocates from ranges but does not reject manually supplied duplicates. Pair DNA with the Attribute Uniqueness plug-in when every value, whether generated or manual, must be unique.

6. Can one DNA range span multiple backends?

No. Keep DNA scope within one database backend. The plug-in duplicate-range checks are not designed to manage one range across multiple databases.
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 experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)