How to Configure LDAP Authentication for Self‑Hosted Applications: A Complete Guide

Configure LDAP authentication by deploying an OpenLDAP server (or 389 Directory Server), securing it with TLS/StartTLS, creating a service bind account, and pointing each application to the directory via environment variables or configuration files like grafana.ini and ldap.toml.

The Self-Hosting-Guide repository provides comprehensive coverage of LDAP integration for self-hosted services. This guide walks through the exact configuration patterns found in the repository's README.md LDAP section, demonstrating how to unify authentication across multiple containers using a central directory.

Architectural Overview of LDAP Authentication

A typical LDAP deployment for self-hosting consists of four layers working together to provide centralized identity management.

The LDAP Server Layer

The LDAP server acts as the authoritative directory for user identities and groups. The Self-Hosting-Guide lists several supported options including OpenLDAP, 389 Directory Server, and Apache Directory Server. You install one of these, populate it with users using ldapadd or a GUI like Apache Directory Studio, and define the schema attributes (e.g., uid, mail, cn) that applications will query.

TLS Encryption Requirements

Secure the bind connection using either LDAPS on port 636 or StartTLS on port 389. This protects credentials in transit between applications and the directory. For OpenLDAP specifically, configure olcTLSCertificateFile and olcTLSCertificateKeyFile in the server configuration, or mount certificates into the container.

Client Application Configuration

Each self-hosted service (such as Nextcloud, Docker Mailserver, or Grafana) binds to the LDAP server using a standard set of parameters:

  • LDAP host and port (389 or 636)
  • Bind DN (service account distinguished name)
  • Bind password (stored in Docker secrets or environment variables)
  • Base DN for user searches (e.g., ou=users,dc=example,dc=org)
  • Attribute mapping to align LDAP fields with application user properties

Reverse Proxy Integration (Optional)

If you front services with Traefik, Caddy, or Nginx, delegate authentication to middleware like Ory Oathkeeper or Keycloak. These tools validate LDAP credentials and set a session cookie or JWT before the request reaches the backend application.

Step‑by‑Step Configuration Guide

Follow these steps to implement LDAP authentication according to the Self-Hosting-Guide patterns.

1. Deploy an OpenLDAP Server

Use the official Docker image to spin up the directory service. The guide recommends osixia/openldap as the primary choice for self-hosted environments.


# docker-compose.yml

version: "3.8"
services:
  openldap:
    image: osixia/openldap:1.5.0
    container_name: openldap
    environment:
      LDAP_ORGANISATION: "My Org"
      LDAP_DOMAIN: "example.org"
      LDAP_ADMIN_PASSWORD: "StrongPassword123"
      LDAP_TLS: "true"
    volumes:
      - ./ldap-data:/var/lib/ldap
      - ./ldap-config:/etc/ldap/slapd.d
    ports:
      - "389:389"
      - "636:636"

Store the admin password in a proper secret store for production deployments.

2. Enable TLS Encryption

Mount TLS certificates into the container or let the image generate self-signed ones. Configure the OpenLDAP TLS parameters to secure authentication traffic.

3. Create a Service Bind Account

Create a low-privilege DN (e.g., cn=binduser,ou=service,dc=example,dc=org) that can search the directory but cannot modify entries. This account prevents applications from having administrative access while still allowing user lookups.

4. Configure Target Applications

Most Docker-based apps expose LDAP variables. The guide provides specific examples for Docker Mailserver and Grafana.

5. Test the Integration

Use ldapsearch from a client container to verify bind and search operations before enabling application-level authentication.

Practical Configuration Examples

Deploying OpenLDAP with Docker Compose

The Self-Hosting-Guide references OpenLDAP as the primary directory option in its README.md LDAP section. The following docker-compose.yml snippet matches the repository's recommended deployment pattern:

version: "3.8"
services:
  openldap:
    image: osixia/openldap:1.5.0
    container_name: openldap
    environment:
      LDAP_ORGANISATION: "My Org"
      LDAP_DOMAIN: "example.org"
      LDAP_ADMIN_PASSWORD: "StrongPassword123"
      LDAP_TLS: "true"
    volumes:
      - ./ldap-data:/var/lib/ldap
      - ./ldap-config:/etc/ldap/slapd.d
    ports:
      - "389:389"
      - "636:636"

Configuring Grafana for LDAP Authentication

Grafana uses a two-file configuration approach. First, enable LDAP in grafana.ini:


# grafana.ini (mounted into the Grafana container)

[auth.ldap]
enabled = true
config_file = /etc/grafana/ldap.toml
allow_sign_up = true

Then specify connection details in ldap.toml:


# ldap.toml

[[servers]]
host = "openldap"
port = 389
use_ssl = false
start_tls = true
bind_dn = "cn=binduser,ou=service,dc=example,dc=org"
bind_password = "SecretBindPwd"
search_filter = "(uid=%s)"
search_base_dns = ["ou=users,dc=example,dc=org"]

Grafana follows the standard pattern of host, bind DN, and search filter to authenticate users against the directory.

Docker Mailserver LDAP Setup

The guide identifies Docker Mailserver as a "full-stack" service with built-in LDAP support. Enable it via environment variables:


# docker-compose.yml snippet

mailserver:
  image: docker.io/mailserver/docker-mailserver:latest
  hostname: mail
  domainname: example.org
  environment:
    - ENABLE_LDAP=1
    - LDAP_SERVER=ldap://openldap:389
    - LDAP_BIND_DN=cn=binduser,ou=service,dc=example,dc=org
    - LDAP_BIND_PW=SecretBindPwd
    - LDAP_BASE_DN=ou=users,dc=example,dc=org
  volumes:
    - maildata:/var/mail
    - mailstate:/var/mail-state
    - ./config/:/tmp/docker-mailserver/
  ports:
    - "25:25"
    - "587:587"
    - "993:993"

Testing with ldapsearch

Verify connectivity using a one-off container before configuring applications:

docker run --rm -it \
  --network=host \
  osixia/openldap:1.5.0 \
  ldapsearch -H ldaps://localhost \
  -D "cn=binduser,ou=service,dc=example,dc=org" \
  -w "SecretBindPwd" \
  -b "ou=users,dc=example,dc=org" \
  "(uid=*)"

If the command returns user entries, authentication is correctly wired.

Security Best Practices

When configuring LDAP authentication for self-hosted applications, follow these guidelines from the Self-Hosting-Guide:

  • Store bind passwords in secret stores (Docker secrets, Kubernetes secrets, or .env files) rather than plain text in compose files
  • Use LDAPS or StartTLS exclusively to avoid transmitting credentials in clear text
  • Map LDAP groups to application roles when supported (e.g., mapping Nextcloud groups to admin/user privileges)
  • Restrict the bind account to read-only access on specific organizational units
  • Enable TLS certificate validation in client applications to prevent man-in-the-middle attacks

Summary

  • Deploy OpenLDAP using the osixia/openldap image with persistent volumes for ldap-data and ldap-config
  • Secure connections via LDAPS on port 636 or StartTLS on port 389 by configuring olcTLSCertificateFile and olcTLSCertificateKeyFile
  • Create a dedicated bind account with limited privileges for applications to query the directory
  • Configure applications using standard environment variables (LDAP_SERVER, LDAP_BIND_DN, LDAP_BASE_DN) or configuration files (grafana.ini, ldap.toml)
  • Test connectivity with ldapsearch before enabling application authentication
  • Optional: Add reverse-proxy authentication using Ory Oathkeeper or Keycloak to centralize session management

Frequently Asked Questions

What is the difference between LDAP and LDAPS?

LDAPS (LDAP over SSL) uses port 636 and establishes an encrypted connection immediately upon connection. Standard LDAP on port 389 transmits data in plain text unless you enable StartTLS, which upgrades the connection to encrypted after the initial handshake. The Self-Hosting-Guide recommends using LDAPS or StartTLS to protect credentials in transit.

Can I use LDAP authentication with Docker Mailserver?

Yes. Docker Mailserver includes native LDAP support. Set ENABLE_LDAP=1 and provide the LDAP_SERVER, LDAP_BIND_DN, LDAP_BIND_PW, and LDAP_BASE_DN environment variables. The mail server will authenticate users against the directory before allowing IMAP or SMTP access.

How do I map LDAP groups to application roles?

Most applications that support LDAP also support group mapping through configuration attributes. In ldap.toml for Grafana or equivalent configuration files, specify the group_search_filter and group_mappings parameters to align LDAP groups (e.g., cn=admins,ou=groups,dc=example,dc=org) with application-specific roles (e.g., Admin, Editor).

Which LDAP server should I choose for self-hosting?

The Self-Hosting-Guide lists OpenLDAP as the primary recommended option due to its widespread adoption and Docker support. Alternatively, you can deploy 389 Directory Server or Apache Directory Server depending on your preference for management interfaces and specific schema requirements.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →