phpLDAPadmin on Ubuntu 24.04 on Azure User Guide
Overview
phpLDAPadmin is the long established open source web interface for administering an LDAP directory. Instead of hand editing LDIF files or working through command line tools, administrators browse the directory as a tree, create and edit entries and attributes against the live schema, import and export LDIF, run searches and manage passwords, all from a browser. This release is the modern rewrite of the application, rebuilt on a current PHP framework with a refreshed interface while keeping the direct, schema aware editing that made the original a standard tool for directory administrators. The cloudimg image is a self contained directory appliance: OpenLDAP (slapd) runs on the instance as the directory backend and phpLDAPadmin 2.3.11 is served by the Apache web server with PHP 8.4 in front of it, all on a hardened, fully patched Ubuntu 24.04 LTS base. The directory is pre organised with ou=People and ou=Groups containers, a directory administrator account and two sample accounts, so the tree browser is populated the moment the instance boots. The directory service is bound to the loopback interface only, every page requires an authenticated session, and a unique set of secrets is generated on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- phpLDAPadmin 2.3.11 (GPL-2.0) served by Apache and PHP 8.4, managed by systemd
- A bundled OpenLDAP (
slapd) directory backend, provisioned with base DNdc=cloudimg,dc=local - A ready made directory layout:
ou=People,ou=Groups, a directory administrator account and two sample accounts in a sample group - Per VM secrets generated on first boot and recorded in a root only file: the directory administrator web login password and the OpenLDAP manager password
- A per VM application session encryption key, so no two instances share the key that protects signed in sessions
- No shipped default login: no known or blank credential authenticates; every secret is rotated to a discarded random at build time and regenerated uniquely on first boot
- Authentication required on every page: an unauthenticated visitor is redirected to the sign in form and can browse nothing
- OpenLDAP bound to the loopback interface
127.0.0.1:389only, never exposed to the network slapd.serviceandapache2.serviceas enabled systemd units- An unauthenticated
/healthzendpoint for Azure Load Balancer health probes - 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 sensible starting point; step up to Standard_D2s_v3 for larger directories or more concurrent administrators. NSG inbound: allow 22/tcp from your management network and 80/tcp for the phpLDAPadmin web interface (add 443/tcp if you terminate TLS on the VM). The directory service is never exposed: slapd listens on 127.0.0.1 only, so port 389 stays off the network.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for phpLDAPadmin 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) and HTTP (80). Then Review + create then Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name phpldapadmin \
--image <marketplace-image-urn> \
--size Standard_B2s \
--admin-username azureuser \
--generate-ssh-keys \
--public-ip-sku Standard
Then open port 80:
az vm open-port --resource-group <your-rg> --name phpldapadmin --port 80
Step 3 - Confirm the services are running
SSH in as azureuser and confirm the directory backend and the web interface are both active. Note that slapd listens only on 127.0.0.1:389 while Apache serves phpLDAPadmin on port 80.
systemctl is-active slapd apache2
ss -tlnp | grep -E ':389 |:80 ' | sed 's/ */ /g'

Step 4 - Retrieve the per VM credentials
Every VM generates its own secrets on first boot and writes them, along with the login account and the application URL, to a root only credentials file. Confirm the file is present and root only, then read the non secret fields:
sudo ls -l /root/phpldapadmin-credentials.txt
sudo grep -vE 'pass=' /root/phpldapadmin-credentials.txt

To read the login password itself, print just that line:
sudo grep '^phpldapadmin.login.pass=' /root/phpldapadmin-credentials.txt | cut -d= -f2-
You sign in to phpLDAPadmin with the User ID ldapadmin and that password. That account is a real directory entry (uid=ldapadmin,ou=People,dc=cloudimg,dc=local) with full write access to the tree, and the application authenticates your sign in by binding to the directory with the credentials you type. The separate phpldapadmin.rootdn.pass value is the OpenLDAP manager (cn=admin) password, used for command line administration on the box; the manager is not a directory entry, so it cannot be used to sign in to the web interface.
Step 5 - Sign in
Browse to http://<vm-public-ip>/. An unauthenticated visitor is redirected straight to the sign in form, so nothing in the directory is browsable until you authenticate.

After signing in you land on the home page, with the directory tree for dc=cloudimg,dc=local in the navigation panel and the server details alongside it.

Step 6 - Browse and edit the directory
Expand dc=cloudimg,dc=local in the tree to reach the ou=People and ou=Groups containers. Selecting an entry opens the entry viewer, which lists every attribute on that object alongside the object classes it belongs to, so you can see exactly what the directory holds.

The same view lets you edit attribute values in place and commit them to the directory, and the tree exposes the containers and groups the image seeded for you. Use the create and import options to add your own entries or load an LDIF file.

Step 7 - No known or default credentials
Nothing in this image ships with a known or blank password. The directory administrator web login password, the OpenLDAP manager password and the application session encryption key are each rotated to a discarded random value at build time and regenerated with a unique random secret on the first boot of every VM. You can prove the credential end to end on the box: the per VM password binds, a wrong password is rejected, and the bundled round trip check confirms both plus a real web sign in through the application's own login form.
DN="$(sudo grep '^phpldapadmin.login.dn=' /root/phpldapadmin-credentials.txt | cut -d= -f2-)"
PW="$(sudo grep '^phpldapadmin.login.pass=' /root/phpldapadmin-credentials.txt | cut -d= -f2-)"
sudo ldapwhoami -x -H ldap://127.0.0.1 -D "$DN" -w "$PW"
sudo ldapwhoami -x -H ldap://127.0.0.1 -D "uid=ldapadmin,ou=People,dc=cloudimg,dc=local" -w 'definitely-the-wrong-password' || echo "wrong password correctly rejected"
sudo bash /usr/local/sbin/phpldapadmin-cred-roundtrip.sh

The application also refuses to serve anything to an anonymous visitor, and its source tree is not reachable over HTTP:
curl -s -o /dev/null -w 'GET / -> %{http_code} %{redirect_url}\n' http://127.0.0.1/
curl -s -o /dev/null -w 'GET /.env -> %{http_code}\n' http://127.0.0.1/.env
Step 8 - Verify the directory and where your data lives
Confirm the loopback binding and inspect the seeded directory. The whole directory (OpenLDAP mdb backend) lives on the single OS disk under /var/lib/ldap, the application under /opt/phpldapadmin, and the directory is never reachable off the instance:
curl -sI http://127.0.0.1/healthz | head -1
sudo ldapsearch -x -H ldap://127.0.0.1 -D "cn=admin,dc=cloudimg,dc=local" -w "$(sudo grep '^phpldapadmin.rootdn.pass=' /root/phpldapadmin-credentials.txt | cut -d= -f2-)" -b "dc=cloudimg,dc=local" -LLL dn
ss -tlnp | grep ':389 ' | sed 's/ */ /g'

Server components
| Component | Version | Location |
|---|---|---|
| phpLDAPadmin | 2.3.11 | /opt/phpldapadmin |
| OpenLDAP (slapd) | Ubuntu 24.04 package | /var/lib/ldap, config in cn=config |
| Apache HTTP Server | Ubuntu 24.04 package | /etc/apache2/sites-available/cloudimg-phpldapadmin.conf |
| PHP | 8.4 | /etc/php/8.4 |
Filesystem layout
| Path | Description |
|---|---|
/opt/phpldapadmin |
Application root; Apache serves only the public subdirectory |
/opt/phpldapadmin/.env |
Application configuration, root only readable by the web user |
/var/lib/ldap |
OpenLDAP mdb directory database |
/var/lib/cloudimg |
First boot sentinel |
/root/phpldapadmin-credentials.txt |
Per VM credentials, mode 0600 |
/var/log/apache2 |
Web server access and error logs |
Managing the services
systemctl status slapd --no-pager
sudo systemctl restart apache2
Adding your own domain and TLS
phpLDAPadmin serves plain HTTP on port 80. For production, point a DNS record at your VM and obtain a certificate with Let's Encrypt:
sudo apt-get install -y certbot python3-certbot-apache
sudo certbot --apache -d <your-domain>
After the certificate is issued, update the application's own base URL so generated links use your domain, then rebuild its configuration cache:
sudo sed -i 's|^APP_URL=.*|APP_URL="https://<your-domain>"|' /opt/phpldapadmin/.env
sudo /usr/bin/php8.4 /opt/phpldapadmin/artisan config:cache
sudo systemctl reload apache2
Backing up
Your directory data is the OpenLDAP database plus its configuration. Export both to LDIF with slapcat:
sudo slapcat -n 0 -l /tmp/phpldapadmin-config-backup.ldif
sudo slapcat -n 1 -l /tmp/phpldapadmin-directory-backup.ldif
Copy both files off the VM on your usual schedule, together with /opt/phpldapadmin/.env. To restore onto a fresh instance, stop slapd, reload the LDIF with slapadd, and restore the configuration file.
Troubleshooting
The sign in form rejects the password. Confirm you are using the ldapadmin User ID and the phpldapadmin.login.pass value, not the phpldapadmin.rootdn.pass value. The OpenLDAP manager (cn=admin) is not a directory entry, so it cannot sign in to the web interface by design. Verify the credential binds directly with the ldapwhoami command in Step 7.
The web interface returns a 500 error. Check the application log and the Apache error log, then rebuild the configuration cache:
sudo tail -20 /var/log/apache2/phpldapadmin-error.log
First boot has not completed. If the credentials file still shows the placeholder text, the first boot service has not finished. Check it with:
systemctl status phpldapadmin-firstboot.service --no-pager
Security notes
- phpLDAPadmin serves plain HTTP on port 80 out of the box. For anything beyond a trusted network, add your own domain and TLS as above, or front the VM with Azure Application Gateway.
- OpenLDAP listens on
127.0.0.1only and is never reachable from the network. The application talks to it locally; administer the directory through the web interface or over SSH. - Every secret is unique per VM and no known or blank credential authenticates. Keep
/root/phpldapadmin-credentials.txtprotected. - The image stores no LDAP bind credential of its own. The application holds no directory password in its configuration; it binds with the credentials you type at sign in.
- The two sample accounts (
jsmith,agarcia) and thedemoteamgroup exist only to populate the interface and carry discarded random passwords. Delete them once you have added your own entries. - Apply operating system updates regularly with
sudo apt update && sudo apt upgrade; unattended security updates are enabled by default.
Support
For assistance, contact cloudimg support:
- Email: support@cloudimg.co.uk
- Response Time: 24/7 with a one hour average response for critical issues
- Website: https://www.cloudimg.co.uk