LDAPS Certificate Trust in Docker Deployments
Trusting an Internal CA for LDAPS in Docker Deployments
Section titled “Trusting an Internal CA for LDAPS in Docker Deployments”Active Directory and most internal directory servers present a certificate issued by a private CA. The rConfig V8 Pro container does not trust that CA out of the box, so LDAPS binds fail until you add it. This page shows how to mount the CA certificate into the container so the trust survives docker compose restart, docker compose down, and image upgrades.
When to use this
Section titled “When to use this”Use this guide if you connect rConfig to LDAP over LDAPS (port 636) or StartTLS (port 389) and see one of these:
- Test Connection on Settings → LDAP Setup fails, with
Can't contact LDAP serverin the response, while the same host and credentials work from another machine. - The bind starts working after you run
update-ca-certificatesinside the container by hand, then fails again after the container is restarted or updated.
If your directory server uses a certificate from a public CA (DigiCert, Sectigo, Let’s Encrypt), the container already trusts it and you do not need this page. If the bind succeeds but login fails with Could not find user in LDAP directory, that is a search problem rather than a certificate problem: check the Base DN and LDAP Login Attribute on the LDAP integration page.
Why manual certificate installation does not persist
Section titled “Why manual certificate installation does not persist”Anything you install with docker exec lands in the container’s writable layer, which is discarded when the container is recreated. Pulling a new rConfig image, editing docker-compose.yml, or running docker compose down all recreate the container and take the certificate with them.
The fix is to keep the certificate on the container host and bind mount it in, the same approach used for encrypted database connections.
PHP’s LDAP extension is a wrapper around OpenLDAP’s client library, so it reads its trust settings from /etc/ldap/ldap.conf and from the LDAPTLS_* environment variables, not from rConfig’s own configuration. There is no CA certificate field in the rConfig LDAP settings form, and setting a certificate path in .env has no effect on LDAP trust.
Prepare the CA certificate
Section titled “Prepare the CA certificate”-
Export the CA certificate from your PKI. On a Windows CA this is usually available from Certification Authority → Properties → View Certificate → Details → Copy to File, or with
certutil -ca.cert ca.cer. -
Confirm it is PEM encoded. A PEM file starts with
-----BEGIN CERTIFICATE-----in a text editor. Windows commonly exports DER, which OpenLDAP cannot read, so convert it:Terminal window openssl x509 -inform der -in ca.cer -out ad-ca.crt -
If your directory certificate was issued by a subordinate (issuing) CA, concatenate the full chain into a single file, issuing CA first, root CA last:
Terminal window cat issuing-ca.crt root-ca.crt > ad-ca.crt -
Place the file on the container host next to your
docker-compose.yml, for example/home/rconfig/certs/ad-ca.crt, and make it world readable. The CA certificate is public information, so no restrictive permissions are needed:Terminal window chmod 644 /home/rconfig/certs/ad-ca.crt
Create the ldap.conf file
Section titled “Create the ldap.conf file”Create /home/rconfig/certs/ldap.conf on the container host with two lines:
TLS_CACERT /certs/ad-ca.crtTLS_REQCERT hardThe path in TLS_CACERT is the path inside the container, set by the volume mount in the next step, not the host path.
TLS_REQCERT hard makes rConfig refuse to bind if the certificate cannot be validated, which is what you want in production. See the gotchas below before reaching for never.
Mount the certificate into the container
Section titled “Mount the certificate into the container”Add two read-only bind mounts and two environment variables to the app service in your docker-compose.yml, alongside the existing entries:
services: app: environment: # ... existing environment entries, unchanged ... - LDAPTLS_CACERT=/certs/ad-ca.crt - LDAPTLS_REQCERT=hard volumes: # ... existing rConfig volume mappings, unchanged ... - /home/rconfig/certs/ad-ca.crt:/certs/ad-ca.crt:ro - /home/rconfig/certs/ldap.conf:/etc/ldap/ldap.conf:roThe mounted ldap.conf is what does the work. The two environment variables cover the same ground for any process that starts with a different configuration file, and cost nothing to set.
Recreate the container so the new mounts and variables take effect:
docker compose up -dOn SELinux hosts (Rocky, RHEL, Fedora), append :z to both mounts, for example - /home/rconfig/certs/ad-ca.crt:/certs/ad-ca.crt:ro,z.
Verify the trust
Section titled “Verify the trust”Go to Settings → LDAP Setup and click Test Connection. A successful test confirms that the container validated the directory certificate and completed the bind with your service account.
Every step of the exchange is written to the activity log. Open Logs → Activity and filter on authentication events to see the bind result and, on a successful user lookup, a line reading Attempting to login using distinguished name: CN=....
Test the certificate chain directly, using the same client library rConfig uses. Pass the bind password through the environment so it stays out of your shell history:
LDAP_BIND_PW='YourBindPassword' docker compose exec -e LDAP_BIND_PW app php -r '$ldap = ldap_connect("ldaps://dc1.corp.example.com:636");ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);var_dump(ldap_bind($ldap, "svc-rconfig@corp.example.com", getenv("LDAP_BIND_PW")));echo ldap_error($ldap), PHP_EOL;'bool(true) followed by Success means the CA is trusted and the bind worked. Can't contact LDAP server means the certificate is still not validating.
If your compose file sets a container_name, docker exec -it rconfig_app works in place of docker compose exec app.