Every user, group, and SSH key in your Dirless directory can be exported with a
single command - as JSON, as standard LDIF you can load into any LDAP server,
or as flat passwd-style files. Leaving Dirless must never be harder
than joining it. Your directory is yours.
Identity systems are the stickiest infrastructure there is: once your UIDs,
groups, and SSH keys live somewhere, moving them is usually painful enough
that nobody does it. We think that is a bug, not a business model. Dirless
users are standard Linux identities - real UIDs, nsswitch.conf,
getent - and the exporter completes the picture: everything you
put in comes back out in open formats, including LDIF that loads directly
into OpenLDAP, 389-ds, or FreeIPA.
The export runs on any enrolled host and includes both your cloud-synced users (from AWS IAM Identity Center) and your portal-managed local users, merged exactly the way your hosts see them through NSS. It is read-only: exporting changes nothing on the backend.
| Format | What you get | Use it for |
|---|---|---|
json (default) |
One document with users, groups, and ssh_keys |
Backups, scripting, restoring later with dirless-cli import |
ldif |
Standard posixAccount / posixGroup entries, SSH keys as sshPublicKey |
Moving to OpenLDAP, 389-ds, or FreeIPA |
passwd |
passwd + group files and one authorized_keys file per user |
Plain local users, air-gapped hosts, "just give me files" |
x. Dirless never
stores password hashes - authentication is SSH-key and certificate based -
so there are no password hashes to export. Set passwords on the destination
system if you need them.
On any host already enrolled with dirless-cli enroll, the backend
URL, credentials, and your age key are read from /etc/dirless/ -
no flags needed. Requires dirless-cli 0.6.0 or newer.
dirless-cli export
{
"users": [
{
"username": "alice",
"uid": 100001,
"gid": 100000,
"gecos": "Alice Anderson",
"home": "/home/alice",
"shell": "/bin/zsh",
"email": "alice@example.com"
}
],
"groups": [
{ "name": "devs", "gid": 100010, "members": ["alice"] }
],
"ssh_keys": {
"alice": "ssh-ed25519 AAAAC3... alice@laptop"
}
}
Exported 1 user(s), 1 group(s), 1 SSH key file(s) [source: merged, format: json]
dirless-cli export --format ldif --base-dn dc=example,dc=com --out export.ldif
The passwd format writes multiple files, so it takes a directory:
dirless-cli export --format passwd --out ./directory-export
tree directory-export
directory-export/
├── passwd # username:x:uid:gid:gecos:home:shell
├── group # name:x:gid:member1,member2
└── authorized_keys/
├── alice # one file per user, ready for ~/.ssh/
└── bob
By default the export merges your cloud-synced and local users the same way
enrolled hosts do (local wins on a username conflict). Use
--source cloud or --source local to export just one side.
For backups you plan to restore with
dirless-cli import, use --source local: the
cloud side re-syncs from your IdP automatically and does not belong in the
local snapshot.
The LDIF export uses only standard schema: inetOrgPerson +
posixAccount for users, posixGroup for groups, and
the widely deployed openssh-lpk ldapPublicKey class for SSH keys.
Entries are placed under ou=users and ou=groups
beneath the base DN you pass with --base-dn.
The export does not create the parent OUs (on an existing tree they would collide), so create them first if your destination tree is empty:
dn: ou=users,dc=example,dc=com
objectClass: organizationalUnit
ou: users
dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups
ldapadd -x -D cn=admin,dc=example,dc=com -W -f bootstrap-ous.ldif
ldapadd -x -D cn=admin,dc=example,dc=com -W -f export.ldif
Then verify a user came through intact, SSH keys and all:
ldapsearch -x -D cn=admin,dc=example,dc=com -W \
-b ou=users,dc=example,dc=com "(uid=alice)" \
uidNumber loginShell sshPublicKey
dn: uid=alice,ou=users,dc=example,dc=com
uidNumber: 100001
loginShell: /bin/zsh
sshPublicKey: ssh-ed25519 AAAAC3... alice@laptop
objectClass: ldapPublicKey, load the two-line
openssh-lpk schema
first (many distributions and Docker images, including
osixia/openldap, already ship it). Users without SSH keys do
not reference the class at all, so they load on a stock server either way.
| Flag | Effect |
|---|---|
--format FORMAT |
json (default), ldif, or passwd |
--source SOURCE |
merged (default), cloud (IdP-synced users only), or local (portal-managed users only) |
--out PATH |
Output file (default: stdout). For --format passwd this is a directory and is required |
--base-dn DN |
Base DN for LDIF entries (default: dc=example,dc=com) |
--config PATH |
Agent config file (default: /etc/dirless/dirless-agent.toml) |
--server / --token / --tenant-id / --age-key |
Run from a non-enrolled machine by passing the backend URL, bearer token, tenant ID, and age private key explicitly |