mirror of
https://github.com/jwinterm/modoboa.git
synced 2026-10-19 05:58:34 +02:00
665 lines
17 KiB
Markdown
665 lines
17 KiB
Markdown
---
|
|
title: manual step to install dovecot component on modoboa
|
|
description: This guide describe how to install dovecot on the modoboa platform
|
|
head:
|
|
- - meta
|
|
- name: 'keywords'
|
|
content: 'modoboa, installation, dovecot, mysql, postgresql, imapd'
|
|
---
|
|
|
|
# Dovecot
|
|
|
|
## introduction
|
|
|
|
Modoboa requires Dovecot 2+ to work so the following documentation is
|
|
suitable for this combination.
|
|
|
|
In this section, we assume dovecot's configuration resides in
|
|
`/etc/dovecot`, all pathes will be relative to this directory.
|
|
|
|
You can find configuration documentation [here](https://doc.dovecot.org/configuration_manual/).
|
|
|
|
This proposed configuration is the one you can find with modoboa-installer.
|
|
|
|
For up to date configuration,
|
|
[take a look here](https://github.com/modoboa/modoboa-installer/tree/master/modoboa_installer/scripts/files/dovecot/conf.d)
|
|
|
|
## Packages
|
|
|
|
For debian and derivative, recommended packages are:
|
|
|
|
```shell
|
|
apt install dovecot-imapd dovecot-lmtpd dovecot-managesieved dovecot-sieve
|
|
```
|
|
|
|
## Mailboxes
|
|
|
|
First, edit the `conf.d/10-mail.conf` and
|
|
set the `mail_location` variable:
|
|
|
|
```txt{2}
|
|
# maildir
|
|
mail_location = maildir:~/Maildir
|
|
```
|
|
|
|
Then, edit the `inbox` namespace and add the following line:
|
|
|
|
```txt
|
|
inbox = yes
|
|
```
|
|
|
|
In order for dovecot to automaticaly create usual folders on account
|
|
creation, edit the `inbox` namespace of `15-mailboxes.conf`:
|
|
|
|
```txt
|
|
mailbox Drafts {
|
|
auto = subscribe
|
|
special_use = \Drafts
|
|
}
|
|
mailbox Junk {
|
|
auto = subscribe
|
|
special_use = \Junk
|
|
}
|
|
mailbox Sent {
|
|
auto = subscribe
|
|
special_use = \Sent
|
|
}
|
|
mailbox Trash {
|
|
auto = subscribe
|
|
special_use = \Trash
|
|
}
|
|
```
|
|
|
|
Starting dovecot 2.2.20+, you can add `autoexpunge` parameter to delete older message, for instance:
|
|
|
|
```txt
|
|
mailbox Trash {
|
|
auto = subscribe
|
|
special_use = \Trash
|
|
autoexpunge=30d
|
|
}
|
|
```
|
|
|
|
With dovecot 2.1+, it ensures all the special mailboxes will be automaticaly created for new accounts.
|
|
|
|
For dovecot 2.0 and older, use the [autocreate](http://wiki2.dovecot.org/Plugins/Autocreate) plugin.
|
|
|
|
### Operations on the file system {#fs_operations}
|
|
|
|
::: warning
|
|
Modoboa needs to access the `dovecot` binary to check its version. To
|
|
find the binary path, we use the `which` command first and then try
|
|
known locations (`/usr/sbin/dovecot` and
|
|
`/usr/local/sbin/dovecot` ). If you
|
|
installed dovecot in a custom location, please tell us where the binary
|
|
is by using the `DOVECOT_LOOKUP_PATH` setting (see
|
|
`settings.py` ).
|
|
:::
|
|
|
|
Three operation types are considered:
|
|
|
|
1. Mailbox creation
|
|
2. Mailbox renaming
|
|
3. Mailbox deletion
|
|
|
|
The first one is managed by Dovecot. The last two ones may be managed by
|
|
Modoboa if it can access the file system where the mailboxes are stored
|
|
(see `admin-params` to activate this
|
|
feature).
|
|
|
|
Those operations are treated asynchronously by a cron script. For
|
|
example, when you rename an e-mail address through the web UI, the
|
|
associated mailbox on the file system is not modified directly. Instead
|
|
of that, a *rename* order is created for this mailbox. The mailbox will
|
|
be considered unavailable until the order is executed (see
|
|
`Postfix configuration <postfix_config>`).
|
|
|
|
Edit the crontab of the user who owns the mailboxes on the file system:
|
|
|
|
```shell
|
|
$ crontab -u <vmail_user> -e
|
|
```
|
|
|
|
And add the following line inside:
|
|
|
|
```txt
|
|
* * * * * python <modoboa_instance>/manage.py handle_mailbox_operations
|
|
```
|
|
|
|
::: warning
|
|
The cron script must be executed by the system user owning the
|
|
mailboxes.
|
|
:::
|
|
|
|
::: warning
|
|
The user running the cron script must have access to the
|
|
`settings.py` file of the modoboa
|
|
instance.
|
|
:::
|
|
|
|
The result of each order is recorded into Modoboa's log.
|
|
|
|
Go to *Modoboa > Logs* to consult them.
|
|
|
|
## Authentication
|
|
|
|
To make the authentication work, edit the
|
|
`conf.d/10-auth.conf` and uncomment the
|
|
following line at the end:
|
|
|
|
```txt{2}
|
|
#!include auth-system.conf.ext
|
|
!include auth-sql.conf.ext
|
|
#!include auth-ldap.conf.ext
|
|
#!include auth-passwdfile.conf.ext
|
|
#!include auth-checkpassword.conf.ext
|
|
#!include auth-vpopmail.conf.ext
|
|
#!include auth-static.conf.ext
|
|
```
|
|
|
|
Then, edit the `conf.d/auth-sql.conf.ext`
|
|
file and add the following content inside:
|
|
```txt
|
|
passdb sql {
|
|
driver = sql
|
|
# Path for SQL configuration file, see example-config/dovecot-sql.conf.ext
|
|
args = /etc/dovecot/dovecot-sql.conf.ext
|
|
}
|
|
|
|
userdb sql {
|
|
driver = sql
|
|
args = /etc/dovecot/dovecot-sql.conf.ext
|
|
}
|
|
```
|
|
|
|
Make sure to activate only one backend (per type) inside your
|
|
configuration (just comment the other ones).
|
|
|
|
Edit the `dovecot-sql.conf.ext` and modify the configuration according to your database engine.
|
|
|
|
::: code-group
|
|
|
|
``` shell [PostgreSQL]
|
|
# For debian and derivative, you need to install postgres connector for dovecot::
|
|
sudo apt install dovecot-pgsql
|
|
```
|
|
|
|
``` shell [MySQL]
|
|
# For debian and derivative, you need to install mysql connector for dovecot::
|
|
sudo apt install dovecot-mysql
|
|
```
|
|
|
|
``` shell [SQLite]
|
|
# For debian and derivative, you need to install sqlite connector for dovecot::
|
|
sudo apt install dovecot-sqlite
|
|
```
|
|
|
|
:::
|
|
|
|
::: code-group
|
|
``` txt [PostgreSQL]
|
|
driver = pgsql
|
|
|
|
connect = host=<postgres socket> dbname=<database> user=<user> password=<password>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
user_query = \
|
|
SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, \
|
|
%mailboxes_owner_gid as gid, '*:bytes=' || mb.quota || 'M' AS quota_rule \
|
|
FROM admin_mailbox mb \
|
|
INNER JOIN admin_domain dom ON mb.domain_id=dom.id \
|
|
INNER JOIN core_user u ON u.id=mb.user_id \
|
|
WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) \
|
|
AND mb.address='%%n' AND dom.name='%%d'
|
|
|
|
password_query = \
|
|
SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, \
|
|
%mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, \
|
|
CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule \
|
|
FROM core_user u \
|
|
INNER JOIN admin_mailbox mb ON u.id=mb.user_id \
|
|
INNER JOIN admin_domain dom ON mb.domain_id=dom.id \
|
|
WHERE (mb.is_send_only IS NOT TRUE OR '%s' NOT IN ('imap', 'pop3'))\
|
|
AND email='%%u' AND is_active AND dom.enabled
|
|
|
|
iterate_query = SELECT email AS user FROM core_user WHERE is_active
|
|
```
|
|
|
|
``` txt [MySQL]
|
|
driver = mysql
|
|
|
|
connect = host=<mysqld socket> dbname=<database> user=<user> password=<password>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
user_query = \
|
|
SELECT '%{home_dir}/%%d/%%n' AS home, %mailboxes_owner_uid as uid, \
|
|
%mailboxes_owner_gid as gid, \
|
|
CONCAT('*:bytes=', mb.quota, 'M') AS quota_rule \
|
|
FROM admin_mailbox mb \
|
|
INNER JOIN admin_domain dom ON mb.domain_id=dom.id \
|
|
INNER JOIN core_user u ON u.id=mb.user_id \
|
|
WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3', 'lmtp')) \
|
|
AND mb.address='%%n' AND dom.name='%%d'
|
|
|
|
password_query = \
|
|
SELECT email AS user, password, '%{home_dir}/%%d/%%n' AS userdb_home, \
|
|
%mailboxes_owner_uid AS userdb_uid, %mailboxes_owner_gid AS userdb_gid, \
|
|
CONCAT('*:bytes=', mb.quota, 'M') AS userdb_quota_rule \
|
|
FROM core_user u \
|
|
INNER JOIN admin_mailbox mb ON u.id=mb.user_id \
|
|
INNER JOIN admin_domain dom ON mb.domain_id=dom.id \
|
|
WHERE (mb.is_send_only=0 OR '%s' NOT IN ('imap', 'pop3')) \
|
|
AND u.email='%%u' AND u.is_active=1 AND dom.enabled=1
|
|
|
|
iterate_query = SELECT email AS user FROM core_user WHERE is_active
|
|
```
|
|
|
|
```txt [SQLite]
|
|
driver = sqlite
|
|
|
|
connect = <path to the sqlite db file>
|
|
|
|
default_pass_scheme = CRYPT
|
|
|
|
password_query = SELECT email AS user, password FROM core_user u INNER JOIN admin_mailbox mb ON u.id=mb.user_id INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE u.email='%Lu' AND u.is_active=1 AND dom.enabled=1
|
|
|
|
user_query = SELECT '<mailboxes storage directory>/%Ld/%Ln' AS home, <uid> as uid, <gid> as gid, ('*:bytes=' || mb.quota || 'M') AS quota_rule FROM admin_mailbox mb INNER JOIN admin_domain dom ON mb.domain_id=dom.id WHERE mb.address='%Ln' AND dom.name='%Ld'
|
|
|
|
iterate_query = SELECT email AS user FROM core_user
|
|
```
|
|
:::
|
|
|
|
|
|
::: info
|
|
Replace values between `<>` with yours.
|
|
:::
|
|
|
|
## OAuth 2 authentication
|
|
|
|
You first need to register Dovecot as an authorized consumer of the
|
|
OAuth2 authentication service provided by Modoboa.
|
|
|
|
To do so, create an application with the following commands:
|
|
|
|
``` shell
|
|
cd <modoboa_instance_path>
|
|
python manage.py createapplication --name=Dovecot --skip-authorization --client-id=dovecot confidential client-credentials
|
|
```
|
|
|
|
On success, you should see an output similar to:
|
|
|
|
``` txt
|
|
New application Dovecot created successfully.
|
|
client_secret: XXXX
|
|
```
|
|
|
|
To enable OAuth2 authentication in Dovecot, edit the `conf.d/10-auth.conf`
|
|
file and update the auth_mechanisms line as follows:
|
|
|
|
``` txt
|
|
auth_mechanisms = plain login oauthbearer xoauth2
|
|
```
|
|
|
|
Then, add the following line at the end:
|
|
|
|
``` txt
|
|
!include auth-oauth2.conf.ext
|
|
```
|
|
|
|
Then, create a file named `conf.d/auth-oauth2.conf.ext` with the following content:
|
|
|
|
``` txt
|
|
passdb {
|
|
driver = oauth2
|
|
mechanisms = xoauth2 oauthbearer
|
|
args = /etc/dovecot/conf.d/dovecot-oauth2.conf.ext
|
|
}
|
|
```
|
|
|
|
Finally, create a file named `conf.d/dovecot-oauth2.conf.ext` with the following content:
|
|
|
|
``` txt
|
|
introspection_mode = post
|
|
introspection_url = https://dovecot:<client_secret>@<hostname of your server>/api/o/introspect/
|
|
username_attribute = username
|
|
tls_ca_cert_file = /etc/ssl/certs/ca-certificates.crt
|
|
active_attribute = active
|
|
active_value = true
|
|
```
|
|
|
|
Replace `<client_secret>` with the value you obtained earlier.
|
|
|
|
## LDAP
|
|
|
|
To make the LDAP authentication work, edit the `conf.d/10-auth.conf`
|
|
and uncomment the following line at the end:
|
|
|
|
``` txt
|
|
!include auth-ldap.conf.ext
|
|
```
|
|
|
|
Then edit the `conf.d/auth-ldap.conf.ext` and edit the passdb section as following.
|
|
|
|
You should comment the userdb section, which will be managed by SQL with modoboa database:
|
|
|
|
``` txt
|
|
passdb {
|
|
driver = ldap
|
|
|
|
# Path for LDAP configuration file, see example-config/dovecot-ldap.conf.ext
|
|
args = /etc/dovecot/dovecot-ldap.conf.ext
|
|
}
|
|
|
|
#userdb {
|
|
#driver = ldap
|
|
#args = /etc/dovecot/dovecot-ldap.conf.ext
|
|
|
|
# Default fields can be used to specify defaults that LDAP may override
|
|
#default_fields = home=/home/virtual/%u
|
|
#}
|
|
```
|
|
|
|
Your own dovecot LDAP configuration file is now `/etc/dovecot/dovecot-ldap.conf.ext`.
|
|
|
|
You can add your default LDAP conf in it, following the
|
|
[official documentation](https://doc.dovecot.org/configuration_manual/authentication/ldap/).
|
|
|
|
### Synchronize dovecot LDAP conf with modoboa LDAP conf
|
|
|
|
To make dovecot LDAP configuration synchronized with modoboa LDAP configuration,
|
|
you should create a dedicated dovecot conf file.
|
|
|
|
At the end of your dovecot configuration file (`dovecot-ldap.conf.ext` ), add the following line:
|
|
|
|
``` txt
|
|
!include_try dovecot-modoboa.conf.ext
|
|
```
|
|
|
|
Then, set modoboa parameter *Enable Dovecot LDAP sync* to *Yes*.
|
|
Then set the *Dovecot LDAP config file* following the previous step
|
|
(*/etc/dovecot/dovecot-modoboa.conf.ext* in the example)
|
|
|
|
The last step is to add the command **update_dovecot_conf** to the cron
|
|
job of modoboa. Then, each time your modoboa LDAP configuration is
|
|
updated, your dovecot LDAP configuration will also be.
|
|
|
|
## LMTP
|
|
|
|
[Local Mail Transport Protocol](http://en.wikipedia.org/wiki/Local_Mail_Transfer_Protocol)
|
|
is used to let Postfix deliver messages to Dovecot.
|
|
|
|
First, make sure the protocol is activated by looking at the `protocols`
|
|
setting (generally inside `dovecot.conf`).
|
|
|
|
It should be similar to the following example:
|
|
|
|
```txt
|
|
protocols = imap pop3 lmtp
|
|
```
|
|
|
|
Then, open the `conf.d/10-master.conf` ,
|
|
look for `lmtp` service definition and add the following content inside:
|
|
|
|
```txt
|
|
service lmtp {
|
|
# stuff before
|
|
unix_listener /var/spool/postfix/private/dovecot-lmtp {
|
|
mode = 0600
|
|
user = postfix
|
|
group = postfix
|
|
}
|
|
# stuff after
|
|
}
|
|
```
|
|
|
|
We assume here that Postfix is *chrooted* within
|
|
`/var/spool/postfix` .
|
|
|
|
Finally, open the `conf.d/20-lmtp.conf` and modify it as follows:
|
|
|
|
```txt
|
|
protocol lmtp {
|
|
postmaster_address = postmaster@<domain>
|
|
mail_plugins = $mail_plugins quota sieve
|
|
}
|
|
```
|
|
|
|
Replace `<domain>` by the appropriate value.
|
|
|
|
::: info
|
|
If you don't plan to apply quota or to use filters, just adapt the
|
|
content of the `mail_plugins` setting.
|
|
:::
|
|
|
|
## Quota
|
|
|
|
Modoboa lets adminstrators define per-domain and/or per-account limits
|
|
(quota). It also lists the current quota usage of each account. Those
|
|
features require Dovecot to be configured in a specific way.
|
|
|
|
Inside `conf.d/10-mail.conf` ,
|
|
add the `quota` plugin to the default activated ones:
|
|
|
|
```txt
|
|
mail_plugins = quota
|
|
```
|
|
|
|
Inside `conf.d/10-master.conf` , update
|
|
the `dict` service to set proper permissions:
|
|
|
|
```txt
|
|
service dict {
|
|
# If dict proxy is used, mail processes should have access to its socket.
|
|
# For example: mode=0660, group=vmail and global mail_access_groups=vmail
|
|
unix_listener dict {
|
|
mode = 0600
|
|
user = <user owning mailboxes>
|
|
#group =
|
|
}
|
|
}
|
|
```
|
|
|
|
Inside `conf.d/20-imap.conf` , activate
|
|
the `imap_quota` plugin:
|
|
|
|
```txt{4}
|
|
protocol imap {
|
|
# ...
|
|
|
|
mail_plugins = $mail_plugins imap_quota
|
|
|
|
# ...
|
|
}
|
|
```
|
|
|
|
Inside `dovecot.conf` , activate the quota
|
|
SQL dictionary backend:
|
|
|
|
```txt{2}
|
|
dict {
|
|
quota = <driver>:/etc/dovecot/dovecot-dict-sql.conf.ext
|
|
}
|
|
```
|
|
|
|
Inside `conf.d/90-quota.conf` , activate
|
|
the *quota dictionary* backend:
|
|
|
|
```txt
|
|
plugin {
|
|
quota = dict:User quota::proxy::quota
|
|
}
|
|
```
|
|
|
|
It will tell Dovecot to keep quota usage in the SQL dictionary.
|
|
|
|
Finally, edit the `dovecot-dict-sql.conf.ext`{.interpreted-text
|
|
role="file"} file and put the following content inside:
|
|
|
|
```txt
|
|
connect = host=<db host> dbname=<db name> user=<db user> password=<password>
|
|
# SQLite users
|
|
# connect = /path/to/the/database.db
|
|
|
|
map {
|
|
pattern = priv/quota/storage
|
|
table = admin_quota
|
|
username_field = username
|
|
value_field = bytes
|
|
}
|
|
map {
|
|
pattern = priv/quota/messages
|
|
table = admin_quota
|
|
username_field = username
|
|
value_field = messages
|
|
}
|
|
```
|
|
|
|
### PostgreSQL users
|
|
|
|
#### Database schema update
|
|
|
|
The `admin_quota` table is created by Django but unfortunately it
|
|
doesn't support `DEFAULT` constraints (it only simulates them when the
|
|
ORM is used).
|
|
|
|
As PostgreSQL is a bit strict about constraint violations,
|
|
you must execute the following query manually:
|
|
|
|
```sql
|
|
db=> ALTER TABLE admin_quota ALTER COLUMN bytes SET DEFAULT 0;
|
|
db=> ALTER TABLE admin_quota ALTER COLUMN messages SET DEFAULT 0;
|
|
````
|
|
|
|
#### Trigger
|
|
|
|
As indicated on [Dovecot's doc](https://doc.dovecot.org/2.4.2/core/plugins/quota.html#quota-plugin-quota),
|
|
you need a trigger to properly update the quota.
|
|
|
|
A working copy of this trigger is available on
|
|
[Github](https://raw.githubusercontent.com/modoboa/modoboa-installer/master/modoboa_installer/scripts/files/dovecot/install_modoboa_postgres_trigger.sql).
|
|
|
|
Download this file and copy it on the server running postgres.
|
|
|
|
Then, execute the following commands:
|
|
|
|
```shell
|
|
$ su - postgres
|
|
$ psql [modoboa database] < /path/to/modoboa_postgres_trigger.sql
|
|
$ exit
|
|
```
|
|
|
|
Replace `[modoboa database]` by the appropriate value.
|
|
|
|
### Forcing recalculation
|
|
|
|
For existing installations, *Dovecot* (\> 2) offers a command to
|
|
recalculate the current quota usages. For example, if you want to update
|
|
all usages, run the following command:
|
|
|
|
```shell
|
|
$ doveadm quota recalc -A
|
|
```
|
|
|
|
Be carefull, it can take a while to execute.
|
|
|
|
## ManageSieve/Sieve
|
|
|
|
Modoboa lets users define filtering rules from the web interface.
|
|
|
|
To do so, it requires *ManageSieve* to be activated on your server.
|
|
|
|
Inside `conf.d/20-managesieve.conf`, make sure the following lines are uncommented:
|
|
|
|
```txt
|
|
protocols = $protocols sieve
|
|
|
|
service managesieve-login {
|
|
# ...
|
|
}
|
|
|
|
service managesieve {
|
|
# ...
|
|
}
|
|
|
|
protocol sieve {
|
|
# ...
|
|
}
|
|
```
|
|
|
|
Finally, configure the `sieve` plugin by editing the `conf.d/90-sieve.conf` file.
|
|
Put the follwing caontent inside:
|
|
|
|
```txt
|
|
plugin {
|
|
# Location of the active script. When ManageSieve is used this is actually
|
|
# a symlink pointing to the active script in the sieve storage directory.
|
|
sieve = ~/.dovecot.sieve
|
|
|
|
#
|
|
# The path to the directory where the personal Sieve scripts are stored. For
|
|
# ManageSieve this is where the uploaded scripts are stored.
|
|
sieve_dir = ~/sieve
|
|
}
|
|
```
|
|
|
|
Restart Dovecot.
|
|
|
|
Now, you can go to the `postfix` section to finish the installation.
|
|
|
|
## Last-login tracking
|
|
|
|
To update the `last_login` attribute of an account after a succesful
|
|
IMAP or POP3 login, you can configure a [post-login
|
|
script](https://wiki.dovecot.org/PostLoginScripting).
|
|
|
|
Open `conf.d/10-master.conf` add the following configuration
|
|
(`imap` and `pop3` services are already defined,
|
|
you just need to update them):
|
|
|
|
```txt
|
|
service imap {
|
|
executable = imap postlogin
|
|
}
|
|
|
|
service pop3 {
|
|
executable = pop3 postlogin
|
|
}
|
|
|
|
service postlogin {
|
|
executable = script-login /usr/local/bin/postlogin.sh
|
|
user = modoboa
|
|
unix_listener postlogin {
|
|
}
|
|
}
|
|
```
|
|
|
|
Then, you must create a script named
|
|
`/usr/local/bin/postlogin.sh` .
|
|
|
|
According to your database engine, the content will differ.
|
|
|
|
::: code-group
|
|
|
|
``` bash [PostgreSQL]
|
|
#!/bin/sh
|
|
|
|
psql -c "UPDATE core_user SET last_login=now() WHERE username='$USER'" > /dev/null
|
|
|
|
exec "$@"
|
|
```
|
|
|
|
``` bash [MySQL]
|
|
#!/bin/sh
|
|
|
|
DBNAME=XXX
|
|
DBUSER=XXX
|
|
DBPASSWORD=XXX
|
|
|
|
echo "UPDATE core_user SET last_login=now() WHERE username='$USER'" | mysql -u $DBUSER -p$DBPASSWORD $DBNAME
|
|
|
|
exec "$@"
|
|
```
|
|
|
|
::: |