LLDAP on Ubuntu 24.04 on Azure User Guide
Overview
LLDAP (Light LDAP) is a lightweight, self hosted authentication and directory server with a friendly web admin UI. It gives small self hosted deployments a single place to manage user accounts and groups, and exposes a standard LDAP interface so services like Nextcloud, Grafana, Gitea, Jellyfin, Portainer and many more can authenticate against one shared directory instead of each keeping its own logins. It is an opinionated, much simpler alternative to running OpenLDAP or Active Directory. The cloudimg image installs LLDAP 0.6.3 as a single self contained systemd service that serves the LDAP endpoint on port 3890 and the web admin UI on port 17170, backed by an embedded SQLite datastore on a dedicated Azure data disk. There is no default login: a unique admin password, JWT signing secret and key seed are generated on the first boot of every VM, so no two instances ever share a credential. Backed by 24/7 cloudimg support.
What is included:
- LLDAP 0.6.3 managed by systemd, serving LDAP on port 3890 and the web admin UI on port 17170
- A unique admin password plus JWT and key seed secrets generated on first boot, recorded in a root only file
- An embedded SQLite datastore on a dedicated Azure data disk at
/var/lib/lldap - A default base DN of
dc=example,dc=comwith the admin ascn=admin,ou=people,dc=example,dc=com - The built in
lldap_admin,lldap_password_managerandlldap_strict_readonlygroups for delegating access lldap.serviceas a systemd unit, enabled and active- No baked or shared credential of any kind in the image
- 24/7 cloudimg support
Prerequisites
An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a comfortable starting point. NSG inbound rules: allow 22/tcp from your management network for SSH, 17170/tcp for the web admin UI, and 3890/tcp for LDAP so downstream services can bind. LLDAP serves the admin UI and LDAP over plain connections; for production, restrict 17170 and 3890 to your VNet or front them with TLS (see Maintenance).
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for LLDAP by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size; under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22). After deployment, add inbound rules for the web admin UI on TCP 17170 and LDAP on TCP 3890. Review the dedicated data disk on the Disks tab, then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name lldap \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--ssh-key-values ~/.ssh/id_ed25519.pub \
--vnet-name <your-vnet> --subnet <your-subnet> \
--public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name lldap --port 17170 --priority 1010
az vm open-port --resource-group <your-rg> --name lldap --port 3890 --priority 1020
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the service is running
systemctl is-active lldap.service
It reports active. LLDAP serves its LDAP endpoint on port 3890 and its web admin UI on port 17170, and all directory data lives on the dedicated Azure data disk mounted at /var/lib/lldap.

Step 5 - Retrieve your admin login
The LLDAP admin username and password are generated uniquely on the first boot of your VM and written to a root only file:
sudo cat /root/lldap-credentials.txt
This file contains LLDAP_ADMIN_USERNAME, LLDAP_ADMIN_PASSWORD, the lldap.url to open in a browser, the lldap.ldap_url for downstream services, the base DN and the admin bind DN. Store the password somewhere safe.

Step 6 - Confirm the web admin UI responds
curl -s -o /dev/null -w 'GET / -> HTTP %{http_code}\n' http://localhost:17170/
It returns HTTP 200, the LLDAP login page served by the web admin on port 17170.
Step 7 - Verify an LDAP bind from the command line
Prove that the per VM admin authenticates over LDAP and that a wrong password is rejected. Read the password from Step 5 first. Because the command embeds your unique password, run it interactively rather than from a script, substituting the value of LLDAP_ADMIN_PASSWORD for <LLDAP_ADMIN_PASSWORD>:
ldapsearch -x -LLL -H ldap://127.0.0.1:3890 -D 'cn=admin,ou=people,dc=example,dc=com' -w '<LLDAP_ADMIN_PASSWORD>' -b 'ou=people,dc=example,dc=com' '(objectclass=person)' cn uid mail
A correct password returns the admin entry (dn: uid=admin,ou=people,dc=example,dc=com). A wrong password is rejected with ldap_bind: Invalid credentials (49). Downstream services bind to the same LDAP endpoint using this bind DN, or a dedicated service account you create in the web UI.

Step 8 - Sign in to the web admin UI
Browse to http://<vm-public-ip>:17170/. LLDAP shows a sign in page; enter admin and the password from Step 5.

Once signed in, the Users page lists every account with its user ID, email, display name and creation date, and lets you create or delete users.

Step 9 - Manage groups
Open Groups to review and manage groups. LLDAP ships with lldap_admin, lldap_password_manager and lldap_strict_readonly for delegating administrative and password reset rights, and you can add your own groups to map onto the roles your downstream services expect.

Step 10 - Edit a user and set a password
Click any user to open its detail page, where you can edit the display name, first and last name, email and avatar, change the user's password, and manage its group memberships.

Step 11 - Point a downstream service at the directory
Most self hosted apps accept LDAP settings directly. Use the VM's address, port 3890, the base DN dc=example,dc=com, and either the admin bind DN or a dedicated service account. For example, a typical service configuration looks like:
LDAP host: <vm-public-ip>
LDAP port: 3890
Base DN: dc=example,dc=com
Bind DN: cn=admin,ou=people,dc=example,dc=com
User search: ou=people,dc=example,dc=com filter (uid={{username}})
Group search: ou=groups,dc=example,dc=com
For anything beyond a lab, create a read only service account in the lldap_strict_readonly group and bind as that account rather than the admin.
Step 12 - Confirm state lives on the dedicated disk
LLDAP's SQLite datastore lives under /var/lib/lldap on the dedicated Azure data disk, so it survives OS changes and can be resized independently:
findmnt /var/lib/lldap
The mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM.
Maintenance
- Admin login: the per VM credentials live in
/root/lldap-credentials.txt. To change the admin password, sign in to the web UI, open the admin user and use Modify password. - Users and groups: manage everything under Users and Groups in the web admin UI, or script it through the LLDAP GraphQL API at
/api/graphql. - Downstream services: point them at LDAP on port
3890with base DNdc=example,dc=com; create a read only service account rather than binding as admin. - Storage: all directory data lives under
/var/lib/lldapon the data disk; back up that volume to protect your users, groups and password hashes. - Service: the unit is
lldap.service; after any change runsudo systemctl restart lldap. - TLS: the web UI and LDAP are served over plain connections; restrict ports
17170and3890to your VNet, or front the web UI with TLS (for example a reverse proxy with your own domain) and enable LDAPS before production use. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.