Files

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 "$@"
```
:::