LDIF(5)

πŸ’– LDIF(5) β€” the ldif glow-up πŸ’–

okay bestie, sit down, hydrate, because we're talking about the LDAP Data Interchange Format, aka ldif, and it's literally the file format manual. file formats manual, no cap. let's get into it πŸ¦‹


✨ NAME ✨

ldif β€” LDAP Data Interchange Format. that's it, that's the name, she's simple and she knows it πŸ’…


🌸 DESCRIPTION 🌸

so the LDAP Data Interchange Format (LDIF) is how we write LDAP entries and change records down in plain text form. that's the whole vibe. LDAP tools like ldapadd(1) and ldapsearch(1) read and write LDIF entry records, and ldapmodify(1) is the one reading LDIF change records. two flavors, one format, iconic ✨

this page is giving you a basic description of LDIF. if you want the formal, official, all-dressed-up specification, that lives in RFC 2849. periodt.


πŸŽ€ ENTRY RECORDS πŸŽ€

LDIF entry records represent directory entries. the basic form is right here:

dn: <distinguished name>
<attrdesc>: <attrvalue>
<attrdesc>: <attrvalue>
<attrdesc>:: <base64-encoded-value>
<attrdesc>:< <URL>
...

so the value can be UTF-8 text, or base64 encoded data, or a URI pointing at where the attribute value actually lives. choices, we love options 🫢

line continuation: if you want a line to keep going, start the next line with a single space or a tab. like this:

dn: cn=Barbara J Jensen,dc=exam
 ple,dc=com

lines that start with a sharp sign (#) are ignored. yeah, # is the comment character, she's just there to vibe and not be read πŸ’œ

multiple attribute values go on separate lines, one after another:

cn: Barbara J Jensen
cn: Babs Jensen

now, if a value contains a non-printing character, or it begins with a space or a colon (:), then the <attrtype> gets followed by a double colon and the value gets encoded in base 64. for example, the value " begins with a space" would be encoded like this:

cn:: IGJlZ2lucyB3aXRoIGEgc3BhY2U=

and if the attribute value is chilling inside a file, the <attrtype> is followed by a :< and a file: URI. so if the value lives in the file /tmp/value, you'd list it like this:

cn:< file:///tmp/value

other URI schemes (like ftp, http) may be supported too. may be. no promises, bestie πŸ™ˆ

oh and β€” multiple entries within the same LDIF file are separated by blank lines. remember that, it matters.


πŸ¦‹ ENTRY RECORD EXAMPLE πŸ¦‹

here's an actual LDIF file with three entries in it. look at her go:

dn: cn=Barbara J Jensen,dc=example,dc=com
cn: Barbara J Jensen
cn: Babs Jensen
objectclass: person
description:< file:///tmp/babs
sn: Jensen

dn: cn=Bjorn J Jensen,dc=example,dc=com
cn: Bjorn J Jensen
cn: Bjorn Jensen
objectclass: person
sn: Jensen

dn: cn=Jennifer J Jensen,dc=example,dc=com
cn: Jennifer J Jensen
cn: Jennifer Jensen
objectclass: person
sn: Jensen
jpegPhoto:: /9j/4AAQSkZJRgABAAAAAQABAAD/2wBDABALD
 A4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQ
 ERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVG
...

quick note, bc it's giving details: the description in Barbara Jensen's entry is being read from file:///tmp/babs, and the jpegPhoto in Jennifer Jensen's entry is encoded using base 64. two different delivery methods, both slay πŸ”₯


🌈 CHANGE RECORDS 🌈

LDIF change records represent directory change requests. every change record starts with a line telling you the distinguished name of the entry getting changed:

dn: <distinguishedname>

changetype: <[modify|add|delete|modrdn]>

then finally the change info itself shows up, and its format depends on what kind of change you picked above. no cap.


πŸ’… changetype of modify

for a modify, the format is one or more of the following.

add a modification:

add: <attributetype>
<attrdesc>: <value1>
<attrdesc>: <value2>
...
-

or, a replace modification:

replace: <attributetype>
<attrdesc>: <value1>
<attrdesc>: <value2>
...
-
if no attributetype lines are given to replace, the entire attribute is to be deleted (if present). so like, careful, bestie.

or, a delete modification:

delete: <attributetype>
<attrdesc>: <value1>
<attrdesc>: <value2>
...
-
if no attributetype lines are given to delete, the entire attribute is to be deleted. yep, the whole thing. gone.

⭐ changetype of add

for a add, the format is:

<attrdesc1>: <value1>
<attrdesc1>: <value2>
...
<attrdescN>: <value1>
<attrdescN>: <value2>

🧚 changetype of modrdn (or moddn)

for a modrdn or moddn, the format is:

newrdn: <newrdn>
deleteoldrdn: 0 | 1
newsuperior: <DN>

where a value of 1 for deleteoldrdn means delete the values forming the old rdn from the entry, and a value of 0 means leave the values as non-distinguished attributes in the entry. and the newsuperior line is optional β€” if you include it, it specifies the new superior to move the entry to. she's optional but powerful, main character energy πŸ‘‘


πŸ“ changetype of delete

for a delete, no additional information is needed in the record. that's it. short, sweet, efficient. we stan a low-effort king πŸ’€


one more thing bestie: attribute values may be presented using base64 or in files, exactly as described for entry records. and lines in change records may be continued the same way described for entry records too. consistency, we love to see it ✨


πŸ‘‘ CHANGE RECORD EXAMPLE πŸ‘‘

this sample LDIF file has a change record of each type of change. collector's edition:

dn: cn=Babs Jensen,dc=example,dc=com
changetype: add
objectclass: person
objectclass: extensibleObject
cn: babs
cn: babs jensen
sn: jensen

dn: cn=Babs Jensen,dc=example,dc=com
changetype: modify
add: givenName
givenName: Barbara
givenName: babs
-
replace: description
description: the fabulous babs
-
delete: sn
sn: jensen
-

dn: cn=Babs Jensen,dc=example,dc=com
changetype: modrdn
newrdn: cn=Barbara J Jensen
deleteoldrdn: 0
newsuperior: ou=People,dc=example,dc=com

dn: cn=Barbara J Jensen,ou=People,dc=example,dc=com
changetype: delete

(and yes the description really is the fabulous babs, because she's fabulous. facts only.)


πŸ’œ INCLUDE STATEMENT πŸ’œ

plot twist β€” the LDIF parser has been extended to support an include statement for referencing other LDIF files. it's not in the original spec, it's a bonus feature. 🎁

the rules:

  • the include statement must be separated from other records by a blank line.
  • the referenced file is specified using a file: URI.
  • all of its contents are incorporated as if they were part of the original LDIF file.
  • and as above, other URI schemes may be supported.

example, here you go:

dn: dc=example,dc=com
objectclass: domain
dc: example

include: file:///tmp/example.com.ldif

dn: dc=example,dc=org
objectclass: domain
dc: example
heads up: this feature is not part of the LDIF specification in RFC 2849, but it's expected to appear in a future revision of that spec. it is supported by the ldapadd(1), ldapmodify(1), and slapadd(8) commands. so go wild, but know that it's a preview πŸ‘€

🌸 SEE ALSO 🌸

go read these next, bestie, they're all connected:

and the literature: "LDAP Data Interchange Format," Good, G., RFC 2849. required reading, no skimming πŸ“–


🫢 ACKNOWLEDGEMENTS 🫢

OpenLDAP Software is developed and maintained by The OpenLDAP Project <http://www.openldap.org/>. and OpenLDAP Software is derived from the University of Michigan LDAP 3.3 Release. give the ancestors their flowers πŸ’


and that's the whole page, bestie. OpenLDAP 2.7.2, dated 2026/10/21, LDIF(5). you're now officially an LDIF girlie. go forth and changetype: slay πŸ’–βœ¨πŸŽ€

πŸ“¦ where this page comes from