Adds LDAP accounts to mailcow-dockerized and enables LDAP (e.g., Active Directory) authentication.
A python script periodically checks and creates new LDAP accounts and deactivates deleted and disabled ones with mailcow API. It also enables LDAP authentication in SOGo and dovecot.
-
Create a
data/ldap
directory. SQLite database for synchronization will be stored there. -
Extend your
docker-compose.override.yml
with an additional container:ldap-mailcow: image: drlight17/ldap-mailcow network_mode: host container_name: mailcowdockerized_ldap-mailcow depends_on: - nginx-mailcow volumes: - ./data/ldap:/db:rw - ./data/conf/dovecot:/conf/dovecot:rw - ./data/conf/sogo:/conf/sogo:rw environment: - LDAP-MAILCOW_LDAP_URI=ldap(s)://dc.example.local - LDAP-MAILCOW_LDAP_BASE_DN=OU=Mail Users,DC=example,DC=local - LDAP-MAILCOW_LDAP_BIND_DN=CN=Bind DN,CN=Users,DC=example,DC=local - LDAP-MAILCOW_LDAP_BIND_DN_PASSWORD=BindPassword - LDAP-MAILCOW_API_HOST=https://mailcow.example.local - LDAP-MAILCOW_API_KEY=XXXXXX-XXXXXX-XXXXXX-XXXXXX-XXXXXX - LDAP-MAILCOW_SYNC_INTERVAL=300 - LDAP-MAILCOW_LDAP_AVA_ATTR=jpegPhoto - LDAP-MAILCOW_LDAP_QUOTA_ATTR=st - LDAP-MAILCOW_LDAP_FILTER=(&(objectClass=user)(objectCategory=person)(memberOf:1.2.840.113556.1.4.1941:=CN=Group,CN=Users,DC=example DC=local)) - LDAP-MAILCOW_SOGO_LDAP_FILTER=objectClass='user' AND objectCategory='person' AND memberOf:1.2.840.113556.1.4.1941:='CN=Group,CN=Users,DC=example DC=local'
-
Configure environmental variables:
LDAP-MAILCOW_LDAP_URI
- LDAP (e.g., Active Directory) URI (must be reachable from within the container). The URIs are in syntaxprotocol://host:port
. For exampleldap://localhost
orldaps://secure.domain.org
LDAP-MAILCOW_LDAP_BASE_DN
- base DN where user accounts can be foundLDAP-MAILCOW_LDAP_BIND_DN
- bind DN of a special LDAP account that will be used to browse for usersLDAP-MAILCOW_LDAP_BIND_DN_PASSWORD
- password for bind DN accountLDAP-MAILCOW_API_HOST
- mailcow API url. Make sure it's enabled and accessible from within the container for both reads and writesLDAP-MAILCOW_API_KEY
- mailcow API key (read/write)LDAP-MAILCOW_SYNC_INTERVAL
- interval in seconds between LDAP synchronizationsLDAP-MAILCOW_LDAP_AVA_ATTR
- LDAP attr, which contains user photo, leave empty or random string if you won't use itLDAP-MAILCOW_LDAP_QUOTA_ATTR
- LDAP attr, which contains user mail quota, leave empty or random string if you won't use it- Optional LDAP filters (see example above). SOGo uses special syntax, so you either have to specify both or none:
-
LDAP-MAILCOW_LDAP_FILTER
- LDAP filter to apply, defaults to(&(objectClass=user)(objectCategory=person))
-
LDAP-MAILCOW_SOGO_LDAP_FILTER
- LDAP filter to apply for SOGo (special syntax), defaults toobjectClass='user' AND objectCategory='person'
-
-
Start additional container:
docker-compose up -d ldap-mailcow
-
Check logs
docker-compose logs ldap-mailcow
-
Restart dovecot and SOGo if necessary
docker-compose restart sogo-mailcow dovecot-mailcow
Container internally uses the following configuration templates:
- SOGo:
/templates/sogo/plist_ldap
- dovecot:
/templates/dovecot/ldap/passdb.conf
These files have been tested against Active Directory running on Windows Server 2019 domain controller. If necessary, you can edit and remount them through docker volumes. Some documentation on these files can be found here: dovecot, SOGo
This tool enables authentication for Dovecot and SOGo, which means you will be able to log into POP3, SMTP, IMAP, and SOGo Web-Interface. You will not be able to log into mailcow UI or EAS using your LDAP credentials by default.
As a workaround, you can hook IMAP authentication directly to mailcow by adding the following code above this line:
$mbox = imap_open ("{dovecot:993/imap/ssl/novalidate-cert}INBOX", $user, $pass);
if ($mbox != false) {
imap_close($mbox);
return "user";
}
As a side-effect, It will also allow logging into mailcow UI using mailcow app passwords (since they are valid for IMAP). It is not a supported solution with mailcow and has to be done only at your own risk!
Users from your LDAP directory will be added (and deactivated if disabled/not found) to your mailcow database. Not vice-versa, and this is by design.
In order to be shown correctly there must be changed this line:
$stmt = $pdo->prepare("UPDATE `mailbox`
SET `custom_attributes` = :custom_attributes
WHERE username = :username");
$stmt->execute(array(
":username" => $mailbox,
":custom_attributes" => json_encode($attributes, JSON_UNESCAPED_UNICODE)
));