LLDAP
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. It exposes a standard LDAP interface, so services such as Nextcloud, Grafana, Gitea, Jellyfin and Portainer can authenticate against one shared directory instead of each keeping its own logins. It is an opinionated, much simpler alternative to OpenLDAP or Active Directory.
This SecureAnyCloud image installs LLDAP 0.6.3 as a single self-contained systemd service. It 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 share a credential.
What you get:
- 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=com, with 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-in or shared credential of any kind in the image
- 24/7 SecureAnyCloud support
Prerequisites
You need 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.
Set these 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 that downstream services can bind.
LLDAP serves the admin UI and LDAP over plain connections. In 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, and search the Marketplace for LLDAP by SecureAnyCloud. 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).
Review the dedicated data disk on the Disks tab, then select Review + create and Create. After deployment, add inbound rules for the web admin UI on TCP 17170 and LDAP on TCP 3890.
Step 2 - Deploy from the Azure CLI
Accept the Marketplace terms, create the VM, and open the web admin UI and LDAP ports.
# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:lldap-ubuntu-24-04:default:latest
az vm create \
--resource-group <your-rg> \
--name lldap \
--image sac1647283583153:lldap-ubuntu-24-04:default:latest \
--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 1020Step 3 - Connect to your VM
Connect over SSH as azureuser.
ssh azureuser@<vm-public-ip>Step 4 - Confirm the service is running
Check that the LLDAP unit is active.
systemctl is-active lldap.serviceThe command reports active. LLDAP serves its LDAP endpoint on port 3890 and its web admin UI on port 17170. 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 on the first boot of your VM and written to a root-only file. Read the file:
sudo cat /root/lldap-credentials.txtThe 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/The command returns HTTP 200, which is 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. The command embeds your unique password, so run it interactively instead of from a script. Replace <LLDAP_ADMIN_PASSWORD> with the value of 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 that 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.
After you sign in, the Users page lists every account with its user ID, email, display name and creation date. From this page you can 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. Add your own groups to map onto the roles that your downstream services expect.
Step 10 - Edit a user and set a password
Select a user to open its detail page. There you can edit the display name, first and last name, email and avatar. You can also 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. A typical service configuration looks like this:
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=comFor anything beyond a lab, create a read-only service account in the lldap_strict_readonly group. Bind as that account instead of 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. It survives OS changes and can be resized independently:
findmnt /var/lib/lldapThe mount is backed by a separate Azure data disk that is captured into the image and re-provisioned on every VM.
Maintenance
- Admin login: the per-VM credentials are in
/root/lldap-credentials.txt. To change the admin password, sign in to the web UI, open the admin user and select 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 instead of 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 in production. - Security patches: unattended-upgrades remains enabled, so the OS continues to receive security updates automatically.
Support
SecureAnyCloud provides 24/7 expert support for this image. Contact sales@secureanycloud.com.
Deploy on Azure
Launch LLDAP on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.
View this image
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com
Overview
LLDAP (Light LDAP) is a lightweight, self-hosted authentication server that speaks LDAP and ships with a simple web admin UI for managing users and groups. It is an opinionated, easy alternative to OpenLDAP or Active Directory for small and mid-size self-hosted deployments. It acts as a single identity backbone for the many applications that already speak LDAP, such as Nextcloud, Gitea, Grafana, Jellyfin and Portainer.
This SecureAnyCloud image runs LLDAP as a single hardened Rust service with an embedded SQLite datastore. The web admin UI is bound to the loopback address 127.0.0.1:17170 and fronted by an nginx reverse proxy that terminates TLS on port 443. The raw web port is never exposed off-box. The LDAP endpoint listens on port 3890 for downstream services and requires bind credentials, so a network probe cannot dump the directory.
A unique admin password, JWT signing secret, key seed and self-signed TLS certificate are generated on the first boot of every instance, so no shared or default credential ships in the image. The directory database lives on a dedicated data volume mounted at /var/lib/lldap.
What you get:
- LLDAP 0.6.3 (a single Rust binary) managed by systemd, serving an LDAP endpoint and a web admin UI
- nginx on port 443 terminating TLS in front of the web admin UI, which is bound to the loopback address
127.0.0.1:17170 - The LDAP endpoint on port 3890 for downstream services, requiring bind credentials (anonymous binds are refused)
- A unique admin password, JWT secret, key seed and self-signed TLS certificate generated on first boot
- The admin credential recorded in a root-only file
- A dedicated data volume at
/var/lib/lldapholding the SQLite directory database lldap.serviceandnginx.serviceas systemd units, enabled and active- 24/7 SecureAnyCloud support
Prerequisites
You need an AWS account, an EC2 key pair in the target region, and a VPC with a public subnet. The recommended instance type is m5.large (2 vCPU / 8 GiB RAM).
Set these security group inbound rules. Allow 22/tcp from your management network for SSH and 443/tcp for the web admin UI over TLS. Allow 3890/tcp for LDAP from the downstream services that authenticate against the directory. In production, restrict this rule to your VPC or application security group.
Step 1 - Launch the AMI
Subscribe to the listing in AWS Marketplace and choose Continue to Launch. Launch through the EC2 console or the AWS CLI. Select the m5.large instance type, your key pair, and a security group that opens ports 22, 443 and 3890.
aws ec2 run-instances \
--image-id <ami-id> \
--instance-type m5.large \
--key-name <your-key-pair> \
--security-group-ids <security-group-id> \
--subnet-id <subnet-id> \
--count 1Step 2 - Connect to your instance
Connect over SSH as the default login user for your operating system variant. For Ubuntu 24.04, the SSH login user is ubuntu.
ssh -i <your-key-pair>.pem ubuntu@<public-ip>Step 3 - Read your unique admin credential
The image generates a unique admin password on first boot and writes it to a root-only file. Read the file:
sudo cat /root/lldap-credentials.txtThe output shows the admin username and password, plus the resolved web and LDAP URLs for this instance:
LLDAP_ADMIN_USERNAME=admin LLDAP_ADMIN_PASSWORD=<LLDAP_ADMIN_PASSWORD> lldap.web_url=https://<public-ip>/ lldap.ldap_url=ldap://<public-ip>:3890 lldap.base_dn=dc=example,dc=com lldap.admin_bind_dn=cn=admin,ou=people,dc=example,dc=comStep 4 - Confirm the services and ports
LLDAP and nginx run under systemd. The web admin UI is bound to loopback only, nginx serves it over TLS on 443, and LDAP listens on 3890:
systemctl is-active lldap.service nginx /opt/lldap/lldap --version sudo ss -tlnp | grep -E ':(443|3890|17170) 'The following output comes from a running instance:
active active lldap 0.6.3 LISTEN 0.0.0.0:443 LISTEN 127.0.0.1:17170 LISTEN 0.0.0.0:3890Port 17170 is bound to 127.0.0.1 only, so the raw web port is not reachable off-box. Only nginx on 443 fronts it.
Step 5 - Sign in to the web admin UI
Open the web admin UI in your browser at https://<public-ip>/. The TLS certificate is self-signed and unique to this instance, so your browser shows a warning the first time. Accept the warning to proceed, or install your own certificate (see Step 9). Sign in as admin with the password from Step 3.
After you sign in, you land on the Users list, which shows every account in the directory:
Step 6 - Create users and groups
Select Create a user to add an account, and give it a user ID, email and display name. Open any user to edit their details or set a password:
Switch to the Groups tab to model teams. Select Create a group, then open the group to add members. Downstream applications can map group membership to roles and permissions:
Step 7 - Confirm authentication from the command line
The ldap-utils client tools ship in the image. Bind as the admin over LDAP and search the directory. Anonymous binds are refused, so downstream services must authenticate:
PW=$(sudo awk -F= '/^LLDAP_ADMIN_PASSWORD=/{print $2}' /root/lldap-credentials.txt) ldapsearch -x -LLL -H ldap://127.0.0.1:3890 \
-D 'cn=admin,ou=people,dc=example,dc=com' -w "$PW" \
-b 'ou=people,dc=example,dc=com' '(objectclass=person)' cn uid mailThe following output comes from an instance with two sample users created in the UI:
dn: uid=admin,ou=people,dc=example,dc=com cn: Administrator mail: admin@example.com uid: admin dn: uid=jsmith,ou=people,dc=example,dc=com cn: Jordan Smith mail: jsmith@example.com uid: jsmithAn anonymous bind is refused. The command below is expected to fail, which shows that a network probe cannot read the directory without credentials:
ldapsearch -x -H ldap://127.0.0.1:3890 -b 'dc=example,dc=com' \
|| echo "Anonymous bind correctly refused."ldap_bind: Inappropriate authentication (48) additional info: Anonymous bind not allowed Anonymous bind correctly refused.Step 8 - Connect a downstream application over LDAP
Point any LDAP-aware application (Nextcloud, Gitea, Grafana, Jellyfin and others) at this directory using these settings:
- LDAP host / port:
<public-ip>/3890 - Bind DN:
cn=admin,ou=people,dc=example,dc=com(or a dedicated read-only service account that you create in the UI) - Base DN:
dc=example,dc=com - User search base:
ou=people,dc=example,dc=com - Group search base:
ou=groups,dc=example,dc=com
In production, create a dedicated service account in the web admin UI instead of binding as admin. Restrict port 3890 in the security group to the application's security group or your VPC CIDR.
Step 9 - Use your own domain and TLS certificate (optional)
The image generates a self-signed certificate per instance at /etc/lldap/tls/cert.pem and /etc/lldap/tls/key.pem. The nginx site at /etc/nginx/sites-available/lldap.conf references both files. To use a certificate for your own domain, replace those two files and reload nginx. For example, use a certificate issued by AWS Certificate Manager and terminated at a load balancer, or one obtained with certbot:
sudo nginx -t && sudo systemctl reload nginxStep 10 - Confirm the directory database is on the dedicated data volume
The SQLite directory database lives on its own EBS volume, which is separate from the OS disk and independently resizable:
findmnt /var/lib/lldap ls -la /var/lib/lldap/users.dbTo protect your directory, snapshot this volume with EBS snapshots or AWS Backup.
Support
SecureAnyCloud provides 24/7 technical support for this product by email and live chat at sales@secureanycloud.com. We can help with deployment, connecting downstream applications over LDAP, TLS termination with your own domain and certificate, user and group modelling, and backup planning for your directory database.
For refunds, contact sales@secureanycloud.com with your AWS account ID and subscription details.
Deploy on AWS
Launch LLDAP with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com