Compatibility

LDAP compatibility, without an LDAP server.

Some applications only speak LDAP - Jenkins plugins, Gitea, VPN concentrators, NAS boxes. Dirless deliberately does not ship an LDAP server; decades of quirky LDAP clients are a support surface nobody should take on twice. Instead, one command renders your directory as a config file for glauth, a widely used single-binary LDAP server, and your LDAP-only apps get their directory back. Requires dirless-cli 0.7.0 or newer.

On this page
Overview

How it fits together

Everything runs on your side, on any enrolled host: the export reads the same local snapshot your hosts already resolve users from, writes a complete glauth configuration - users, groups, SSH keys, secondary memberships - and glauth serves it over LDAP to your network. The Dirless backend is not involved, and nothing new is exposed anywhere.

dirless-cli export --format glauth reads your directory on an enrolled host
writes
/etc/glauth/dirless.cfg complete config: users, groups, SSH keys
served by
glauth ldap://your-host:3893, on your network only
answers LDAP queries from
Jenkins · Gitea · VPN · NAS anything that only speaks LDAP
Keep it off the public internet. Bind glauth to localhost or your private network, exactly as you would any directory service. The generated config listens on 127.0.0.1:3893 until you change it.

Step 1

Generating the config

Install glauth (a single binary from its releases page, or your distribution's package), then generate the config on any enrolled host:

Shell (enrolled host)
dirless-cli export --format glauth --base-dn dc=example,dc=com --out /etc/glauth/dirless.cfg

The output is a complete, runnable glauth configuration: every user with their UID, shell, home, mail, secondary groups, and SSH keys; every group with its GID; and synthesized entries for user-private groups so that DNs resolve cleanly. Like every Dirless export it is generated locally - snapshots are decrypted on your machine with your age key.


Step 2

The service account

glauth denies anonymous searches, so your LDAP consumers need an account to bind with. The generated config ends with a commented-out template - uncomment it, set a password hash, and give the credentials to your applications:

/etc/glauth/dirless.cfg (uncommented template)
[[users]]
  name = "search"
  uidnumber = 64999
  primarygroup = 64999
  passsha256 = "..."   # echo -n 'YOUR-PASSWORD' | sha256sum

  [[users.capabilities]]
    action = "search"
    object = "*"

[[groups]]
  name = "svcaccts"
  gidnumber = 64999

The bind DN for this account is cn=search,ou=svcaccts,dc=example,dc=com. The capabilities block matters: without it the account can bind but every search is refused.


Step 3

Running and verifying

Run glauth however you run services; a systemd unit is the common choice, shown here as an example rather than a prescription:

Example: /etc/systemd/system/glauth.service
[Unit]
Description=glauth LDAP server (Dirless directory)
After=network.target

[Service]
ExecStart=/usr/local/bin/glauth -c /etc/glauth/dirless.cfg
Restart=on-failure

[Install]
WantedBy=multi-user.target

Then confirm a user resolves, SSH keys and all:

Shell
ldapsearch -x -H ldap://127.0.0.1:3893 \
  -D 'cn=search,ou=svcaccts,dc=example,dc=com' -W \
  -b dc=example,dc=com '(uid=alice)' uidNumber loginShell sshPublicKey

dn: cn=alice,ou=alice,ou=users,dc=example,dc=com
uidNumber: 100001
loginShell: /bin/zsh
sshPublicKey: ssh-ed25519 AAAAC3... alice@laptop

Step 4

Keeping it fresh

An export is a point-in-time picture. Directory changes are infrequent, so a periodic re-export is all it takes - again as an example, a systemd timer that regenerates the config and restarts glauth:

Example: /etc/systemd/system/glauth-refresh.service
[Unit]
Description=Regenerate glauth config from Dirless

[Service]
Type=oneshot
ExecStart=/usr/bin/dirless-cli export --format glauth \
  --base-dn dc=example,dc=com --out /etc/glauth/dirless.cfg.new
ExecStart=/bin/sh -c 'cat /etc/glauth/service-account.cfg >> /etc/glauth/dirless.cfg.new'
ExecStart=/bin/mv /etc/glauth/dirless.cfg.new /etc/glauth/dirless.cfg
ExecStart=/bin/systemctl restart glauth
Example: /etc/systemd/system/glauth-refresh.timer
[Unit]
Description=Refresh glauth config every 5 minutes

[Timer]
OnCalendar=*:0/5

[Install]
WantedBy=timers.target
Keep your service account out of the regenerated file. The example above appends it from a separate service-account.cfg on every refresh, so re-exports never wipe your credentials. Any equivalent scheme (cron, Ansible, a configuration manager) works just as well - the only contract is "re-export, re-append, restart".

Reference

Quirks and limitations

BehaviorWhat to know
Groups are ou= entries glauth serves groups as ou=devs,ou=users,<base>, not cn=devs,ou=groups,<base>. Filter on (objectClass=posixGroup) - matching on cn finds nothing.
No bind-as-user Dirless stores no password hashes, so exported users can be found but cannot bind. Apps that verify logins via LDAP bind need passwords added to glauth by hand; apps that only look up users and groups work as-is.
Point-in-time data glauth serves the last export. The refresh timer bounds the lag; pick an interval that matches how often your directory changes.
Not our LDAP server glauth is an independent open source project. Dirless generates its config - protocol behavior, TLS setup, and tuning are documented by the glauth project.

What's next