---
title: "Dovecot"
lastUpdated: 2025-11-01
slug: ispmail-trixie/dovecot
sidebar:
  order: 165
---

import { Aside } from "@astrojs/starlight/components";
import StepListReceive from "../../../components/StepListReceive.astro";

<StepListReceive currentStep={4} />

In this chapter we will configure Dovecot so that it knows how to deliver incoming emails.

## Setting up the vmail directory

On your disk all the mailboxes will live in the directory `/var/vmail`. To separate the mailboxes from the rest of your
system, let's create a new user and group that will own the mailboxes:

```sh title="Run this on your server"
groupadd --system vmail
useradd --system --gid vmail vmail
mkdir -p /var/vmail
chown -R vmail:vmail /var/vmail
chmod u=rwx,g=rx,o= /var/vmail
```

## Dovecot configuration

The configuration files for Dovecot are found in `/etc/dovecot/conf.d`. All these files are loaded by Dovecot. This is
done by this magical line at the end of the `/etc/dovecot/dovecot.conf` file:

```
!include conf.d/*.conf
```

It loads all files in `/etc/dovecot/conf.d/` that end in “.conf" in alphanumerical order. Let's edit a couple of files
for our purpose.

### 10-auth.conf

The `/etc/dovecot/conf.d/10-auth.conf` file is dealing with authentication. At the end of this file you will find a list
of authentication backends that Dovecot ships with. By default it will use _system users_ (those from /etc/passwd). But
we want to use the MariaDB database backend. Please comment out all include statements:

```text title="Edit your /etc/dovecot/conf.d/10-auth.conf"
#!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-static.conf.ext
```

Every line starting with `#` is disabled. Only lines starting with `!` are considered.

### 10-mail.conf / 99-ispmail-mail.conf

The file at `/etc/dovecot/conf.d/10-mail.conf` contains many settings regarding mailboxes, like where they are located,
who owns them and what is their layout? Create a new file `/etc/dovecot/conf.d/99-ispmail-mail.conf` that overrides
these defaults:

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-mail.conf << EOF
mail_driver = maildir
mail_home = /var/vmail/%{user | domain}/%{user | username}
mail_path = ~/Maildir
mail_uid = vmail
mail_gid = vmail
mail_inbox_path = ~/Maildir/
EOF
```

This looks more sophisticated than with versions of Dovecot before 2.4. What it means:

- **mail_driver**: Mailboxes are stored in
  [maildir](https://doc.dovecot.org/2.4.1/core/config/mailbox_formats/maildir.html#maildir-mailbox-format) format.
- **mail_home**: Every mail user gets their own _home_ directory in `/var/vmail/DOMAIN/USER`. The `user` variable
  contains the email address like `john@example.org`. The expression `user | domain` splits off the _domain_ part from
  the email address. Similarly `user | username` takes the part before the `@` sign.
- **mail_path**: Within the _home_ directory the actual mailbox will live in a subdirectory called `Maildir`. The reason
  is that we will store other data in the user's _home_ directory as well that should not conflict with the mailbox
  directory.
- **mail_uid**/**mail_gid**: All mailboxes will be owned be the user and group `vmail`.
- **mail_inbox_path**: A user's main inbox consists of the directories `cur` and `new` inside the Maildir directory. We
  used that schema in previous guides and make sure you can migrate your mailboxes from other mail servers. This
  overrides the setting in in `10-mail.conf`.

### 10-master.conf / 99-ispmail-master.conf

This configuration file at `/etc/dovecot/conf.d/10-master.conf` deals with Dovecot's _services_. A _service_ is a part
of Dovecot that listens on a TCP port or a UNIX socket so that other parts of your system can use it. We want Postfix to
use Dovecot for authentication. So we need to change the `service auth` section:

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-master.conf << EOF
service auth {
  unix_listener /var/spool/postfix/private/dovecot-auth {
    mode = 0660
    user = postfix
    group = postfix
  }
}
EOF
```

That way Dovecot will put a communication socket into `/var/spool/postfix/private/dovecot-auth`. It will allow Postfix
to authenticate your users which is relevant later when we set up _relaying_.

### 10-ssl.conf / 99-ispmail-ssl.conf

Earlier in this guide you created both a key and a certificate file to encrypt the communication with IMAPS and HTTPS
between the users and your mail server. You need to tell Dovecot where to find these files. Also set
[ssl=required](https://doc.dovecot.org/2.4.1/core/config/ssl.html#how-to-specify-when-ssl-tls-is-required) to prevent
that someone sends their password without encryption. Again we will create a new file `99-ispmail-ssl.conf` to override
the defaults.

<Aside type="danger" title="Important">

Please replace `mail.example.org` by the FQDN you chose.

</Aside>

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-ssl.conf << EOF
ssl = required
ssl_server_cert_file = /etc/letsencrypt/live/mail.example.org/fullchain.pem
ssl_server_key_file = /etc/letsencrypt/live/mail.example.org/privkey.pem
EOF
```

### 20-lmtp.conf / 99-ispmail-lmtp.conf

There is one setting in the `/etc/dovecot/conf.d/20-lmtp.conf` that will mess up the recipient's email address in our
setup: `auth_username_format`. So let's override it:

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-lmtp-username-format.conf << EOF
protocol lmtp {
  auth_username_format =
}
EOF
```

### 99-ispmail-sql.conf

Let's tell Dovecot where to find information on an valid users (_userdb_) and their passwords (_passdb_). There are
suggestions in the `auth-sql.conf.ext` file but we will add our own file:

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-sql.conf << EOF
sql_driver = mysql

mysql /var/run/mysqld/mysqld.sock {
  user = mailserver
  password = 'MAILSERVER-PASSWORD-HERE'
  dbname = mailserver
  host = 127.0.0.1
}

userdb sql {
  query = SELECT email as user FROM virtual_users WHERE email='%{user}'
  iterate_query = SELECT email as user FROM virtual_users
}

passdb sql {
  query = SELECT password FROM virtual_users where email='%{user}'
}
EOF

# fix permissions
chown root:root /etc/dovecot/conf.d/99-ispmail-sql.conf
chmod go= /etc/dovecot/conf.d/99-ispmail-sql.conf
```

Dovecot can also read the path to a user's home directory and the user-ID and group-ID from the database. Our setup has
a fixed schema for the home directory (`/var/vmail/DOMAIN/USER`) (as defined by `mail_home`) and the user and group are
always `vmail` and `vmail`.

### 99-ispmail-managesieve.conf

Later, we will implement server-side automation using **Sieve** rules. By default, Dovecot exposes two TCP ports to the
internet: 2000 and 4190. Port 2000 is deprecated anyway and can be safely disabled, while port 4190 is the one we will
use. However, unless you have a compelling reason, it is recommended not to make this port publicly accessible. So let
us restrict it to the _localhost_ interface:

```sh title="Run this on your server"
cat > /etc/dovecot/conf.d/99-ispmail-managesieve.conf << EOF
service managesieve-login {
  # Listen only on localhost
  inet_listener sieve {
    listen= 127.0.0.1
    port = 4190
  }

  # Disable the deprecated listener
  inet_listener sieve_deprecated {
    port = 0
  }
}
EOF
```

_(Thanks to Thomas Gauweiler for spotting that.)_

## Restart and test

Restart Dovecot from the shell:

```sh title="Run this on your server"
systemctl restart dovecot
```

Check your logs:

```sh title="Run this on your server"
journalctl -fu dovecot
```

You should see:

```
dovecot[13309]: master: Dovecot v2.4.1-4 (7d8c0e5759) starting up for imap, lmtp, sieve (core dumps disabled)
systemd[1]: Started dovecot.service - Dovecot IMAP/POP3 email server.
```

If you get any error messages please double-check your configuration files.

<Aside type="tip" title="Why there is no /var/log/mail.log?">

In previous guides we used to check the log output from Postfix and Dovecot in a file called `/var/log/mail.log`.
However in the age of _systemd_ the output of the processes is written to systemd's _journal_ instead.

To read the complete logs of Dovecot, run (u=unit):

```sh title="Run this on your server"
journalctl -u dovecot
```

To `tail -f` the logs (f=follow):

```sh title="Run this on your server"
journalctl -fu dovecot
```

However on a busy server it will show the entire journal and then follow any changes. You may want to limit the output
to the last 10 lines:

```sh title="Run this on your server"
journalctl -n 10 -fu dovecot
```

If you prefer the old way of having log files, just install the `rsyslog` package.

</Aside>

<Aside icon="approve-check-circle" title="Test it">

To test the `userdb` query:

```sh title="Run this on your server"
doveadm user john@example.org
```

That should give you:

```
field     value
uid       vmail
gid       vmail
home	    /var/vmail/example.org/john
mail_path	/var/vmail/example.org/john/Maildir
```

To test the `iterate` query that gets a list of all users:

```sh title="Run this on your server"
doveadm user '*'
```

As there is currently only one user the output should be:

```
john@example.org
```

</Aside>
