# How do I make Jitsi Meet moderators log in with LDAP or Active Directory?

> Jitsi checks moderator passwords against LDAP through Prosody's Cyrus SASL module and the saslauthd daemon, which binds to your directory. On Docker set ENABLE_AUTH=1, ENABLE_GUESTS=1, AUTH_TYPE=ldap and the LDAP_* variables, with a filter that matches the attribute users type as their login. Test with testsaslauthd inside the prosody container and ldapsearch from a throwaway container. On packages install sasl2-bin, libsasl2-modules-ldap, lua-cyrussasl, prosody-modules and mod_auth_cyrus, and configure /etc/saslauthd.conf by hand.

Source: https://jitsi.help/guides/jitsi-ldap-authentication/
Updated: October 5, 2026
Publisher: Jitsi Help (https://jitsi.help/)

## Who this is for

You want only people in your directory (OpenLDAP, Active Directory, Samba AD or Authentik's LDAP outpost) to start meetings on your Jitsi server. Guests should still be able to join once a host is in. You want hosts to use their normal directory password.

## How it works

**The chain.** Jitsi Meet shows a login dialog. Prosody receives the username and password with SASL PLAIN and hands them to Cyrus SASL through `mod_auth_cyrus`. Cyrus SASL sends them to the `saslauthd` daemon over a local socket. saslauthd searches the directory with `ldap_filter`, then binds as the user to check the password. Prosody never talks to LDAP itself.

**Docker specifics.** With `AUTH_TYPE=ldap`, the prosody container renders `/run/saslauthd.conf` from the `LDAP_*` variables. If you mount your own `/etc/saslauthd.conf`, that file is copied instead. It starts `saslauthd -a ldap -O /run/saslauthd.conf -c -m /var/run/saslauthd -n 5 -d`. `-c` caches credentials and `-d` logs to the container output. Prosody uses `authentication = "cyrus"` with `cyrus_application_name = "xmpp"` and `allow_unencrypted_plain_auth = true`. The image ships `/etc/sasl/xmpp.conf` with `pwcheck_method: saslauthd` and `mech_list: PLAIN`.

**What changed with rootless containers.** Since stable-11146, Prosody and saslauthd run as user `s6` (uid 1000) on a read-only root filesystem. Config is rendered into `/run`. Mounting your own `/etc/saslauthd.conf` still works, because the script only reads it. On stable-11146 to 11146-2, saslauthd could fail with `could not open pid lock file: /var/run/saslauthd/saslauthd.pid.lock` because that folder was owned by root. This was reported on Podman and fixed in stable-11248 by PR #2312.

**Who becomes moderator.** Jicofo auth follows `ENABLE_AUTH` in Docker, and an authenticated Jicofo makes every logged-in user a moderator. So to limit who can host, restrict the LDAP filter, for example to a group.

**Future note.** A Jitsi maintainer wrote in June 2026 that "native LDAP will be going away at some point" and suggested OIDC for new setups.

## Before you start

- Jitsi with HTTPS at `https://meet.example.com`: docker-jitsi-meet stable-11248, or packages 2.0.11248 with secure domain set up.
- A service account that can search the directory, and its DN.
- The base DN where users live, and the attribute users will type as their login: `uid` (OpenLDAP), `sAMAccountName` (AD), or `cn` (Authentik, where `uid` is a generated identifier).
- Network access from the prosody container or host to the directory: usually 389 (LDAP or StartTLS) or 636 (LDAPS).
- For TLS with a private CA: the root CA certificate in PEM format.

## Steps

### Docker (docker-jitsi-meet stable-11248)

1. **Choose your directory settings** in `.env`. Common to all:

   ```ini
   ENABLE_AUTH=1
   ENABLE_GUESTS=1
   AUTH_TYPE=ldap
   LDAP_AUTH_METHOD=bind
   LDAP_VERSION=3
   ```

   **OpenLDAP:**

   ```ini
   LDAP_URL=ldaps://ldap.example.com/
   LDAP_BASE=ou=people,dc=example,dc=com
   LDAP_BINDDN=cn=jitsi,ou=services,dc=example,dc=com
   LDAP_BINDPW=REPLACE_WITH_BIND_PASSWORD
   LDAP_FILTER=(uid=%u)
   ```

   **Active Directory** (handbook example filter). The group clause uses AD's `memberOf` attribute:

   ```ini
   LDAP_URL=ldaps://dc1.example.com/
   LDAP_BASE=DC=example,DC=com
   LDAP_BINDDN=CN=jitsi,OU=Service Accounts,DC=example,DC=com
   LDAP_BINDPW=REPLACE_WITH_BIND_PASSWORD
   LDAP_FILTER=(&(sAMAccountName=%u)(memberOf=CN=Jitsi Hosts,OU=Groups,DC=example,DC=com))
   ```

   **Authentik LDAP outpost.** The bind DN form comes from Authentik's docs, and the working filter and port come from issue #2259:

   ```ini
   LDAP_URL=ldap://203.0.113.10:3389/
   LDAP_BASE=dc=ldap,dc=goauthentik,dc=io
   LDAP_BINDDN=cn=jitsi-service,ou=users,dc=ldap,dc=goauthentik,dc=io
   LDAP_BINDPW=REPLACE_WITH_APP_PASSWORD
   LDAP_FILTER=(cn=%u)
   ```

   If users type `alice@example.com`, use `%U` (the user part) instead of `%u`.

2. **Turn on certificate checks.** The image sets `TLS_REQCERT allow` in `/etc/ldap/ldap.conf`. With `allow`, a bad certificate "will be ignored and the session proceeds normally". saslauthd only enforces checks when `ldap_tls_check_peer` is set, and the template only writes it when both of these are on:

   ```ini
   LDAP_USE_TLS=1
   LDAP_TLS_CHECK_PEER=1
   ```

   For a private CA on stable-11248, put the PEM file in `~/.jitsi-meet-cfg/prosody/config/`. That folder is mounted at `/config`. Then point to it:

   ```ini
   LDAP_TLS_CACERT_FILE=/config/ldap-ca.crt
   ```

   For StartTLS, use an `ldap://` URL and set `LDAP_START_TLS=1`. Newer images add a `${CONFIG}/prosody/custom-ca` folder (PR #2334), but it is not in a stable release yet.

3. **Recreate Prosody** so the new environment is rendered:

   ```bash
   docker compose up -d --force-recreate prosody
   ```

4. **Test the password check inside the container** with the service name Prosody uses (`xmpp`):

   ```bash
   docker compose exec prosody testsaslauthd -u alice -p 'REPLACE_WITH_PASSWORD' -s xmpp -f /var/run/saslauthd/mux
   ```

5. **Test the bind and lookup with ldapsearch.** The prosody image has no `ldap-utils`, and its root filesystem is read-only. Run a throwaway Debian container on the same network instead:

   ```bash
   NET=$(docker network ls --format '{{.Name}}' | grep 'meet.jitsi$')
   docker run --rm -it --network "$NET" debian:trixie-slim sh -c '
     apt-get update -qq && apt-get install -y -qq ldap-utils >/dev/null &&
     ldapsearch -x -H ldaps://ldap.example.com -D "cn=jitsi,ou=services,dc=example,dc=com" -W \
       -b "ou=people,dc=example,dc=com" "(uid=alice)" dn uid cn sAMAccountName'
   ```

   For a private CA, add `-v ~/.jitsi-meet-cfg/prosody/config/ldap-ca.crt:/ca.crt:ro -e LDAPTLS_CACERT=/ca.crt` to `docker run`.

### Debian/Ubuntu packages (2.0.11248)

1. **Install the SASL pieces**:

   ```bash
   sudo apt-get install sasl2-bin libsasl2-modules-ldap lua-cyrussasl prosody-modules
   sudo prosodyctl install --server=https://modules.prosody.im/rocks/ mod_auth_cyrus
   ```

2. **Create `/etc/saslauthd.conf`** using the same keys the Docker template writes:

   ```ini
   ldap_servers: ldaps://ldap.example.com
   ldap_bind_dn: cn=jitsi,ou=services,dc=example,dc=com
   ldap_bind_pw: REPLACE_WITH_BIND_PASSWORD
   ldap_auth_method: bind
   ldap_search_base: ou=people,dc=example,dc=com
   ldap_filter: (uid=%u)
   ldap_tls_check_peer: yes
   ldap_tls_cacert_file: /etc/ssl/certs/ca-certificates.crt
   ```

3. **Test, then enable the service**:

   ```bash
   sudo saslauthd -d -a ldap
   sudo testsaslauthd -u alice -p 'REPLACE_WITH_PASSWORD'
   sudo sed -i -e "s/START=.*/START=yes/" -e "s/MECHANISMS=.*/MECHANISMS=\"ldap\"/" /etc/default/saslauthd
   sudo service saslauthd restart
   ```

   Run the first command in one terminal, the test in a second, then stop the first with Ctrl+C before enabling the service.

4. **Create the Cyrus config for Prosody** in `/etc/sasl/prosody.conf` (the name matches the default `cyrus_application_name`):

   ```bash
   sudo mkdir -p /etc/sasl
   printf 'pwcheck_method: saslauthd\nmech_list: PLAIN\n' | sudo tee /etc/sasl/prosody.conf
   ```

5. **Switch Prosody to Cyrus and give it socket access**:

   ```bash
   sudo sed -i -E -e "/^ *VirtualHost \"$(hostname -f)\"/,/^ *VirtualHost/ {s/authentication ?=.*$/authentication = \"cyrus\"/}" /etc/prosody/conf.avail/$(hostname -f).cfg.lua
   sudo adduser prosody sasl
   sudo service prosody restart
   ```

## Configuration reference

| Name | Where | Default | What it does |
|---|---|---|---|
| `AUTH_TYPE` | Docker `.env` | `internal` | `ldap` renders `/run/saslauthd.conf` and loads `auth_cyrus` |
| `LDAP_URL` | Docker `.env` | none | `ldap_servers` |
| `LDAP_BASE` | Docker `.env` | none | `ldap_search_base` |
| `LDAP_BINDDN` / `LDAP_BINDPW` | Docker `.env` | unset (anonymous) | `ldap_bind_dn` / `ldap_bind_pw` |
| `LDAP_FILTER` | Docker `.env` | `uid=%u` | `ldap_filter` |
| `LDAP_AUTH_METHOD` | Docker `.env` | `bind` | `ldap_auth_method` |
| `LDAP_VERSION` | Docker `.env` | `3` | `ldap_version` |
| `LDAP_USE_TLS` | Docker `.env` | `0` | Enables the TLS block below |
| `LDAP_TLS_CHECK_PEER` | Docker `.env` | `0` | `ldap_tls_check_peer: yes`, only with `LDAP_USE_TLS=1` |
| `LDAP_TLS_CACERT_FILE` / `LDAP_TLS_CACERT_DIR` | Docker `.env` | `/etc/ssl/certs/ca-certificates.crt` / `/etc/ssl/certs` | CA trust for peer checks |
| `LDAP_TLS_CIPHERS` | Docker `.env` | unset | `ldap_tls_ciphers` |
| `LDAP_START_TLS` | Docker `.env` | `0` | `ldap_start_tls: yes`, needs `ldap://` |
| `ENABLE_GUESTS` | Docker `.env` | `0` | Guests join on the anonymous domain once a host is in |
| `cyrus_application_name` | Prosody VirtualHost | `prosody` (Docker sets `xmpp`) | Name of `/etc/sasl/<name>.conf` |
| `allow_unencrypted_plain_auth` | Prosody VirtualHost | unset (Docker sets `true`) | Allows PLAIN without TLS |
| `TLS_REQCERT` | `/etc/ldap/ldap.conf` | `allow` in the Docker image | libldap certificate policy |

Filter tokens: `%u` is the user, `%U` the user part before `@`, `%d` the domain part, `%r` the realm.

## Common mistakes

- **`auth failure: [user=alice] [service=xmpp] [realm=meet.jitsi] [mech=ldap] [reason=Unknown]`**. In issue #2259 the service bind worked but the filter matched nobody. The `not found, update pending` line just before it is the credential cache missing, not the directory. Check the attribute with ldapsearch. In Authentik, `uid` is a hash, so use `cn=%u` or `sAMAccountName=%u`. Also check that the user is under `LDAP_BASE`.
- **`No available SASL mechanisms, verify that the configured authentication module 'cyrus' is loaded and configured correctly`.** The auth module did not load. On Ubuntu 24.04 and newer packages, install `prosody-modules` and `mod_auth_cyrus`. On Docker it came from broken builds: 7210-1 (fixed in 7210-2) and an early hardened image (fixed by PR #2269 before stable-11146).
- **`No Cyrus SASL mechanisms available`** at Prosody startup. The Cyrus config file is missing or has the wrong name for `cyrus_application_name`.
- **Login rejected with `not-authorized`.** Cyrus returned an authentication failure (SASL_BADAUTH): wrong password, or the user's bind was refused. Test with `testsaslauthd`.
- **`could not open pid lock file: /var/run/saslauthd/saslauthd.pid.lock`.** Upgrade to stable-11248 (PR #2312).
- **StartTLS with an `ldaps://` URL.** StartTLS needs `ldap://`.
- **`LDAP_TLS_CHECK_PEER=1` without `LDAP_USE_TLS=1`.** The check is never written, so certificates are not verified.
- **Packages: Prosody cannot reach the socket.** `/var/run/saslauthd/` is limited to `root` and group `sasl`, so run `adduser prosody sasl`.
- **Setting only `PROSODY_AUTH_TYPE=ldap`.** The Docker config script checks `AUTH_TYPE` when it renders `saslauthd.conf`.

## Verify

```bash
docker compose exec prosody testsaslauthd -u alice -p 'REPLACE_WITH_PASSWORD' -s xmpp -f /var/run/saslauthd/mux
```

Expect `0: OK "Success."`. A wrong password gives `0: NO "authentication failed"`.

Then log in as host from the browser and watch the logs:

```bash
docker compose logs -f prosody | grep -E 'saslauthd|Authenticated as'
```

A working login shows `auth success: [user=alice] [service=xmpp]` (or `auth success (cached)` on a repeat), then `Authenticated as alice@meet.jitsi` (your `XMPP_DOMAIN`).

Check the rendered config without printing the password:

```bash
docker compose exec prosody grep -v bind_pw /run/saslauthd.conf
```

## If it still fails

- `docker compose logs prosody | grep saslauthd`. saslauthd runs with `-d`, so each attempt shows `[login=...]`, `[realm=...]` and a `reason`.
- Bind errors with the right password: check `LDAP_BINDDN` with ldapsearch `-D` and `-W`.
- TLS errors after enabling peer checks: the server certificate must chain to `LDAP_TLS_CACERT_FILE`, and the URL host must match the certificate name.
- Packages: read `/var/log/auth.log` for `saslauthd` lines.
- Everyone in LDAP can host: that is expected. Narrow `LDAP_FILTER` to a group.

## What we have not confirmed yet

We checked everything above against the docker-jitsi-meet templates and image, the handbook, the cyrus-sasl source and maintainer comments on 2026-10-05. We have not yet tested every directory type against stable-11248. These points are still open:


- Whether the saslauthd lock file error also hit Docker (not only Podman) on stable-11146 to 11146-2.
- How long `saslauthd -c` caches credentials in the container, and whether a password change needs a Prosody restart.
- The Docker template writes `ldap_tls_key` and `ldap_tls_cert` (Prosody's own certificate) when `LDAP_USE_TLS=1`. Whether that client certificate causes problems with directories that request one.
- Whether `LDAP_TLS_CACERT_FILE=/config/ldap-ca.crt` works as described on stable-11248. Not tested on a real server.
- Authentik's outpost port (3389 in issue #2259) depends on how the outpost container is published. Authentik's docs only mention 636 for LDAPS.
- Whether Debian 13 (Prosody 13) needs anything beyond the handbook's Ubuntu 24.04 package list.
- Maintainers have not given a timeline for removing native LDAP.

## Sources

- [Jitsi handbook, LDAP Authentication](https://jitsi.github.io/handbook/docs/devops-guide/ldap-authentication), last changed 2025-06-22, official doc
- [Jitsi handbook, Self-Hosting Guide: Docker (Authentication using LDAP, Trusting custom CA certificates)](https://jitsi.github.io/handbook/docs/devops-guide/devops-guide-docker), source last changed 2026-10-02, official doc
- [docker-jitsi-meet prosody/rootfs/defaults/saslauthd.conf at stable-11248](https://github.com/jitsi/docker-jitsi-meet/blob/stable-11248/prosody/rootfs/defaults/saslauthd.conf), source code
- [docker-jitsi-meet prosody s6 scripts config and saslauthd at stable-11248](https://github.com/jitsi/docker-jitsi-meet/tree/stable-11248/prosody/rootfs/etc/s6-overlay/scripts), source code
- [docker-jitsi-meet prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua at stable-11248](https://github.com/jitsi/docker-jitsi-meet/blob/stable-11248/prosody/rootfs/defaults/conf.d/jitsi-meet.cfg.lua), source code
- [docker-jitsi-meet prosody/Dockerfile and prosody/rootfs/etc/sasl/xmpp.conf at stable-11248](https://github.com/jitsi/docker-jitsi-meet/blob/stable-11248/prosody/Dockerfile), source code
- [mod_auth_cyrus.lua and sasl_cyrus.lua shipped in the prosody image](https://github.com/jitsi/docker-jitsi-meet/tree/stable-11248/prosody/rootfs/prosody-plugins), source code
- [docker-jitsi-meet issue #2259 Authentik LDAP: Prosody binds successfully but returns "Unknown" user](https://github.com/jitsi/docker-jitsi-meet/issues/2259), 2026-06-19 to 2026-06-20, maintainer comments (saghul, emrahcom) and community solution
- [docker-jitsi-meet release stable-11248, PR #2312 and issue #2311](https://github.com/jitsi/docker-jitsi-meet/releases/tag/stable-11248), 2026-09-14, release note and community report
- [docker-jitsi-meet issue #2267 and PR #2269 fix(prosody): replace the failing mv with cp](https://github.com/jitsi/docker-jitsi-meet/pull/2269), merged 2026-06-22, maintainer PR
- [docker-jitsi-meet issue #1272 LDAP auth not working with v7210-1](https://github.com/jitsi/docker-jitsi-meet/issues/1272), 2022-04-25, maintainer comment (saghul)
- [jitsi/handbook PR #544 Update ldap-authentication.md (prosody-modules on Ubuntu 24.04)](https://github.com/jitsi/handbook/pull/544), 2024-12-06, official doc change
- [docker-jitsi-meet issue #1358, maintainer comment on "No available SASL mechanisms"](https://github.com/jitsi/docker-jitsi-meet/issues/1358), 2022-08-08, maintainer comment (damencho)
- [docker-jitsi-meet PR #2334 feat: Add support for custom CA](https://github.com/jitsi/docker-jitsi-meet/pull/2334), merged 2026-10-01, maintainer PR (not in a stable release on 2026-10-05)
- [docker-jitsi-meet PR #2258 feat: Rootless containers](https://github.com/jitsi/docker-jitsi-meet/pull/2258), merged 2026-06-19, maintainer PR
- [cyrus-sasl saslauthd/lak.c (config keys, ldap_tls_check_peer, filter tokens), cache.c and saslauthd-main.c (log lines)](https://github.com/cyrusimap/cyrus-sasl/blob/master/saslauthd/lak.c), checked 2026-10-05, source code
- [Debian man pages testsaslauthd(8) and saslauthd(8), sasl2-bin 2.1.28](https://manpages.debian.org/trixie/sasl2-bin/testsaslauthd.8.en.html), official doc (Debian)
- [Debian man pages ldapsearch(1) and ldap.conf(5)](https://manpages.debian.org/trixie/libldap-common/ldap.conf.5.en.html), official doc (Debian/OpenLDAP)
- [Authentik docs, LDAP provider (bind DN, attributes, LDAPS)](https://docs.goauthentik.io/add-secure-apps/providers/ldap/), checked 2026-10-05, official doc (Authentik)
- [Microsoft, Member-Of attribute (Active Directory schema)](https://learn.microsoft.com/en-us/windows/win32/adschema/a-memberof), official doc (Microsoft)
- [docker-jitsi-meet jicofo.conf template at stable-11248 and jicofo ChatRoomRoleManager.kt](https://github.com/jitsi/jicofo/blob/master/jicofo/src/main/kotlin/org/jitsi/jicofo/xmpp/muc/ChatRoomRoleManager.kt), checked 2026-10-05, source code
- [docker-jitsi-meet docker-compose.yml at stable-11248 (prosody volumes and LDAP_* environment)](https://github.com/jitsi/docker-jitsi-meet/blob/stable-11248/docker-compose.yml), 2026-09-14, source code

## Need a hand?

Directory logins fail in quiet ways. [Contact our engineers](/contact/?topic=troubleshooting) with the saslauthd lines from `docker compose logs prosody` (remove passwords first), or see our [support plans](/services/jitsi-support/).

## Frequently asked questions

### Can only some LDAP users be moderators?

Yes, by limiting who can log in at all, for example with a `memberOf` clause in the filter. Every user who logs in becomes a moderator.

### Do guests need LDAP accounts?

No. With `ENABLE_GUESTS=1` they join anonymously after a host has started the meeting.

### Is LDAP the recommended way for new setups?

A maintainer said native LDAP "will be going away at some point" and pointed to OIDC. If your directory also offers OIDC, consider that route.

### Can I use group nesting or extra saslauthd options?

Yes. Mount your own `/etc/saslauthd.conf` into the prosody container and it is used instead of the generated one. The full key list is in the cyrus-sasl source.


---

Jitsi Help is an independent service. It is not affiliated with, endorsed by or sponsored by 8x8, Inc. or the Jitsi project. Jitsi and Jitsi Meet are trademarks of 8x8, Inc., used here only to describe the software we host and support.
