Ad
Developer Tools Azure

Apache Directory Server on Ubuntu 24.04 on Azure User Guide

| Product: Apache Directory Server on Ubuntu 24.04 LTS on Azure

Overview

Apache Directory Server (ApacheDS) is an extensible, embeddable LDAP v3 and Kerberos directory server written in Java by the Apache Software Foundation. It is a standards-compliant directory you can use for centralised authentication, user and group management, application service accounts, and as a backing store for any LDAP-aware application. The cloudimg image installs the official ApacheDS 2.0.0.AM27 binary distribution to /opt, runs it under a dedicated apacheds system user on OpenJDK 17, stores the instance (directory partitions, configuration, working directory and logs) on a dedicated Azure data disk at /var/lib/apacheds, seeds a demo directory tree, and rotates a unique administrator password into the image on first boot. Backed by 24/7 cloudimg support.

What is included:

  • ApacheDS 2.0.0.AM27 (Apache-2.0) running on OpenJDK 17
  • The directory instance (partitions, config, logs) on a dedicated 30 GiB Azure data disk at /var/lib/apacheds
  • A seeded demo partition dc=cloudimg,dc=local with sample inetOrgPerson users and a group, so queries return data out of the box
  • A unique per-VM administrator password generated on first boot (no shared default credential)
  • Loopback-only LDAP (10389) and LDAPS (10636) listeners with authentication enforced (not exposed publicly)
  • 24/7 cloudimg support

This is a directory-server product: ApacheDS listens on 127.0.0.1:10389 (LDAP) and 127.0.0.1:10636 (LDAPS) only. The ports are not opened to the internet - connect locally on the VM or over an SSH tunnel.

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + subnet in the target region. Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. NSG inbound: allow 22/tcp from your management network. No inbound application ports are needed because ApacheDS is reached over the SSH tunnel.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Apache Directory Server 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) only. Then Review + create -> Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name apacheds \
  --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

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm ApacheDS is installed and running

ApacheDS runs as the apacheds.service systemd unit and binds LDAP/LDAPS to loopback only. Check the Java version, the service state and the listeners:

java -version
systemctl is-active apacheds
ss -tln | grep -E '10389|10636'

You should see OpenJDK 17, active, and listeners on 127.0.0.1 for 10389 and 10636:

openjdk version "17.0.19" 2026-04-21
active
LISTEN 0  50  [::ffff:127.0.0.1]:10636  *:*
LISTEN 0  50  [::ffff:127.0.0.1]:10389  *:*

ApacheDS version, service status and loopback listeners

Step 5 - Retrieve your per-VM admin password

Each VM generates its own unique ApacheDS administrator password on first boot and writes it to a root-only credentials file:

sudo cat /root/apacheds-credentials.txt

The file contains APACHEDS_ADMIN_PASSWORD, the bind DN uid=admin,ou=system, the demo base DN dc=cloudimg,dc=local, the loopback host/ports and the SSH-tunnel instructions. Store the password in your secrets manager. In the commands below, <APACHEDS_ADMIN_PASSWORD> stands for the value of APACHEDS_ADMIN_PASSWORD.

Step 6 - Run an anonymous rootDSE query

ApacheDS permits an anonymous read of the rootDSE so clients can discover server capabilities and naming contexts without credentials:

ldapsearch -x -LLL -H ldap://127.0.0.1:10389 -s base -b '' namingContexts supportedLDAPVersion
namingContexts: ou=system
namingContexts: dc=cloudimg,dc=local
supportedLDAPVersion: 3

dc=cloudimg,dc=local is the seeded demo partition.

Step 7 - Search the seeded demo directory tree

Bind as the administrator and list the seeded directory tree under dc=cloudimg,dc=local:

ldapsearch -x -LLL -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' \
  -b 'dc=cloudimg,dc=local' '(objectclass=*)' dn
dn: dc=cloudimg,dc=local
dn: ou=people,dc=cloudimg,dc=local
dn: ou=groups,dc=cloudimg,dc=local
dn: uid=alice,ou=people,dc=cloudimg,dc=local
dn: uid=bob,ou=people,dc=cloudimg,dc=local
dn: cn=engineers,ou=groups,dc=cloudimg,dc=local

Seeded demo directory tree dc=cloudimg,dc=local

Step 8 - Authenticated search for user attributes

Filter for the seeded inetOrgPerson users and return selected attributes - this proves the authenticated bind and the directory data:

ldapsearch -x -LLL -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' \
  -b 'dc=cloudimg,dc=local' '(objectclass=inetOrgPerson)' cn sn mail uid
dn: uid=alice,ou=people,dc=cloudimg,dc=local
mail: alice@cloudimg.local
sn: Anderson
cn: Alice Anderson
uid: alice

dn: uid=bob,ou=people,dc=cloudimg,dc=local
mail: bob@cloudimg.local
sn: Brown
cn: Bob Brown
uid: bob

Authenticated bind and search returns the seeded inetOrgPerson entries

Step 9 - Add your own entry

Add a new user with ldapadd. Create an LDIF file and import it:

cat > /tmp/carol.ldif <<'LDIF'
dn: uid=carol,ou=people,dc=cloudimg,dc=local
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: person
objectClass: top
cn: Carol Carter
sn: Carter
uid: carol
mail: carol@cloudimg.local
LDIF
ldapadd -x -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' -f /tmp/carol.ldif
adding new entry "uid=carol,ou=people,dc=cloudimg,dc=local"

Search for it, then remove it with ldapdelete:

ldapsearch -x -LLL -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' \
  -b 'dc=cloudimg,dc=local' '(uid=carol)' cn mail
ldapdelete -x -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' \
  'uid=carol,ou=people,dc=cloudimg,dc=local'

Step 10 - Confirm authentication is enforced

A wrong administrator password is rejected with LDAP result code 49 (Invalid credentials), so the directory is never readable with a bad credential. Run ldapsearch with a deliberately wrong password (note the non-runnable block below - it is expected to fail by design):

$ ldapsearch -x -H ldap://127.0.0.1:10389 \
    -D 'uid=admin,ou=system' -w WRONG-PASSWORD \
    -b 'dc=cloudimg,dc=local' '(objectclass=*)'
ldap_bind: Invalid credentials (49)
    additional info: INVALID_CREDENTIALS: Bind failed: ERR_229 Cannot authenticate user uid=admin,ou=system

The bind fails immediately with result: 49, confirming authentication is enforced before any directory data is returned.

A wrong admin password is rejected - result 49 Invalid credentials

Step 11 - Connect remotely over an SSH tunnel

ApacheDS listens on 127.0.0.1:10389 (LDAP) and 127.0.0.1:10636 (LDAPS) only and is not exposed publicly - this is the secure default. To reach it from your workstation, open an SSH tunnel and point a local LDAP client at localhost:10389:

# On your workstation:
ssh -L 10389:127.0.0.1:10389 azureuser@<vm-public-ip>

# In another terminal, with a local ldap-utils install:
ldapsearch -x -H ldap://127.0.0.1:10389 \
  -D 'uid=admin,ou=system' -w '<APACHEDS_ADMIN_PASSWORD>' \
  -b 'dc=cloudimg,dc=local' '(objectclass=*)'

For production remote access without a tunnel, bind ApacheDS to a private NIC and front it with TLS via the LDAPS listener on 10636. Never expose the LDAP port to the internet without transport encryption and access controls.

Maintenance

  • Persistence: the directory instance (JDBM partitions, configuration, logs and working directory) lives on the dedicated data disk at /var/lib/apacheds, so the directory survives reboots and the volume is independently resizable.
  • Admin password: rotate it with an ldapmodify that replaces userPassword on uid=admin,ou=system, or change it in /root/apacheds-credentials.txt for reference. The per-VM password is generated once at first boot.
  • Service control: sudo systemctl restart apacheds restarts the directory; journalctl -u apacheds shows the logs.
  • Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
  • Compatibility: ApacheDS is a standard LDAP v3 server - existing LDAP clients, libraries and tooling work unchanged against 10389/10636.

Support

cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.

Apache Directory Server, ApacheDS and the Apache feather logo are trademarks of the Apache Software Foundation. This image is provided by cloudimg and is not affiliated with or endorsed by the Apache Software Foundation.