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

Short answer

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.

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:

    Config
    ENABLE_AUTH=1
    ENABLE_GUESTS=1
    AUTH_TYPE=ldap
    LDAP_AUTH_METHOD=bind
    LDAP_VERSION=3

    OpenLDAP:

    Config
    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:

    Config
    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:

    Config
    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:

    Config
    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:

    Config
    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:

    Terminal
    docker compose up -d --force-recreate prosody
  4. Test the password check inside the container with the service name Prosody uses (xmpp):

    Terminal
    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:

    Terminal
    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:

    Terminal
    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:

    Config
    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:

    Terminal
    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):

    Terminal
    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:

    Terminal
    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

Terminal
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:

Terminal
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:

Terminal
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

Need a hand?

Directory logins fail in quiet ways. Contact our engineers with the saslauthd lines from docker compose logs prosody (remove passwords first), or see our support plans.

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.

Stuck, or would rather not do this by hand?

Deploy it in one click

A private Jitsi server in your own AWS account with SSL, your domain and optional recording, transcription and JWT. Free 15 minute trial.

Start free trial

Talk to a Jitsi engineer

Setup, fixes, branding, recording, scaling. Tell us what is happening and we reply with a plan and a quote.

Get expert help

Related

Recently updated