DEBOPS.DOVECOT(5)

NAME
debops.dovecot - Manage Dovecot IMAP/POP3 server using Ansible

SYNOPSIS

debops run service/dovecot [--limit group,host,...] [--diff] [--check] [--tags tag1,tag2,...] [--skip-tags tag1,tag2,...] [<ansible-playbook options>] ...

DESCRIPTION

The dovecot daemon, maintained by the Dovecot Project <https://www.dovecot.org/>, is a modern IMAP and POP3 email server for Linux/UNIX-like systems, written with security primarily in mind. Dovecot is an excellent choice for both small and large installations. It’s fast, simple to set up, requires no special administration and it uses very little memory.

The debops.dovecot Ansible role can be used to configure the dovecot service on a host and to automatically setup various auxiliary roles, such as debops.pki for SSL/TLS encryption.

GETTING STARTED

  Example inventory

To enable the dovecot service on a host, you need to add it to the [debops_service_dovecot] Ansible inventory group:

[debops_service_dovecot]
hostname

  Default setup

If you don't specify any configuration values, the role will setup dovecot with IMAP, IMAPS, LMTP <https://doc.dovecot.org/configuration_manual/protocols/lmtp_server/>, Sieve <https://doc.dovecot.org/configuration_manual/sieve/pigeonhole_sieve_interpreter/> and Quota <https://doc.dovecot.org/configuration_manual/quota/> support.

In addition, LDAP will automatically be enabled if the host is already configured to use debops.ldap, otherwise dovecot will be configured to allow every user which is able to login via PAM to also login via IMAP and access their emails.

  Other resources

List of other useful resources related to the debops.dovecot Ansible role:

•   Manual pages: for example, dovecot(1) <https://manpages.debian.org/dovecot(1)>, doveconf(1) <https://manpages.debian.org/doveconf(1)> and doveadm(1) <https://manpages.debian.org/doveadm(1)>

•   The website of the Dovecot Project <https://www.dovecot.org/>, in particular the configuration documentation <https://doc.dovecot.org/>

  Example playbook

If you are using the role without DebOps, here's an example Ansible playbook that uses the debops.dovecot role:

---
- name: Manage Dovecot service
  collections: [ 'debops.debops', 'debops.roles01',
                 'debops.roles02', 'debops.roles03' ]
  hosts: [ 'debops_service_dovecot' ]
  become: True
  environment: '{{ inventory__environment | d({})
                   | combine(inventory__group_environment | d({}))
                   | combine(inventory__host_environment  | d({})) }}'
  pre_tasks:
    - name: Prepare dovecot environment
      ansible.builtin.import_role:
        name: 'dovecot'
        tasks_from: 'main_env'
      tags: [ 'role::dovecot', 'role::secret', 'role::ferm' ]
    - name: Prepare postfix environment
      ansible.builtin.import_role:
        name: 'postfix'
        tasks_from: 'main_env'
      vars:
        postfix__dependent_maincf:
          - role: 'dovecot'
            config: '{{ dovecot__postfix__dependent_maincf }}'
        postfix__dependent_mastercf:
          - role: 'dovecot'
            config: '{{ dovecot__postfix__dependent_mastercf }}'
      tags: [ 'role::postfix', 'role::secret', 'role::ferm' ]
  roles:
    - role: secret
      tags: [ 'role::secret', 'role::postfix' ]
      secret__directories:
        - '{{ postfix__secret__directories }}'
    - role: etc_services
      tags: [ 'role::etc_services', 'skip::etc_services' ]
      etc_services__dependent_list:
        - '{{ dovecot__etc_services__dependent_list }}'
    - role: ferm
      tags: [ 'role::ferm', 'skip::ferm' ]
      ferm__dependent_rules:
        - '{{ dovecot__ferm__dependent_rules }}'
    - role: postfix
      tags: [ 'role::postfix', 'skip::postfix' ]
      postfix__dependent_maincf:
        - role: 'dovecot'
          config: '{{ dovecot__postfix__dependent_maincf }}'
      postfix__dependent_mastercf:
        - role: 'dovecot'
          config: '{{ dovecot__postfix__dependent_mastercf }}'
    - role: python
      tags: [ 'role::python', 'skip::python', 'role::ldap' ]
      python__dependent_packages3:
        - '{{ ldap__python__dependent_packages3 }}'
      python__dependent_packages2:
        - '{{ ldap__python__dependent_packages2 }}'
    - role: ldap
      tags: [ 'role::ldap', 'skip::ldap' ]
      ldap__dependent_tasks:
        - '{{ dovecot__ldap__dependent_tasks }}'
    - role: dovecot
      tags: [ 'role::dovecot', 'skip::dovecot' ]

  Ansible tags

You can use Ansible --tags or --skip-tags parameters to limit what tasks are performed during Ansible runs. This can be used after a host is first configured to speed up playbook execution when you are sure that most of the configuration has not been changed.

Available role tags:

role::dovecot
    Main role tag, should be used in the playbook to execute all of the role tasks as well as role dependencies.

role::dovecot:conf
    Main configuration tag, should be used in the playbook to execute all of the role tasks relates to configuration creation.

role::covecot:conf:sql
    SQL specific configuration subtag.

role::dovecot:conf:ldap
    LDAP specific configuration subtag.

role::dovecot:user
    Limited to dovecot user configuration tasks.

role::dovecot:group
    Limited to dovecot group configuration tasks.

DEFAULT VARIABLES: CONFIGURATION

Some of debops.dovecot default variables have more extensive configuration than simple strings or lists, here you can find documentation and examples for them.

  dovecot__features

Currently supported features for dovecot__features are:

imap
    IMAP4rev2 (RFC 9051 <https://datatracker.ietf.org/doc/html/rfc9051.html>) with explicit TLS support via STARTTLS, typically using port 143.

imaps
    IMAP4rev2 with implicit TLS support, typically using port 993.

pop3
    POP3 (RFC 1939 <https://datatracker.ietf.org/doc/html/rfc1939.html>, extensions from RFC 2449 <https://datatracker.ietf.org/doc/html/rfc2449.html> and authentication from RFC 1734 <https://datatracker.ietf.org/doc/html/rfc1734.html>) with explicit TLS support via STARTTLS, typically using port 110.

pop3s
    POP3 with implicit TLS support, typically using port 995.

sieve
    Support for mail filtering/sorting using Sieve (RFC 5228 <https://datatracker.ietf.org/doc/html/rfc5228.html>) scripts and the ManageSieve protocol (RFC 5804 <https://datatracker.ietf.org/doc/html/rfc5804.html>, both with various extensions from other RFCs), the latter typically using port 4190. See Dovecot's ManageSieve Documentation <https://doc.dovecot.org/admin_manual/pigeonhole_managesieve_server/> for further details.

quota
    Support for per-user mail quotas. See Dovecot's Quota Plugin Documentation <https://doc.dovecot.org/configuration_manual/quota_plugin/> for further details.

dsync
    Support for two-directional/pairwise dsync synchronization between two dovecot servers using dovecot's own dsync protocol, typically using port 12345. See Dovecot's Replication Documentation <https://doc.dovecot.org/configuration_manual/replication/> for further details.

    Note that imaps and pop3s (implicit TLS) are recommended over imap and pop3 (explicit TLS) by RFC 8314 <https://datatracker.ietf.org/doc/html/rfc8314.html>. Furthermore, LMTP is recommended over LDA by the Dovecot project.

  DSync Replication

Dovecot supports master/master replication using dsync. The replication is done asynchronously, so high latency between the replicas isn't a problem. The replication is done by looking at Dovecot index files (not what exists in the filesystem), so no mails get lost due to filesystem corruption or an accidental deletion, they will simply be replicated back.

Replication works only between server pairs. Currently dsync is only supported together with a virtual email user since dsync would need root access otherwise.

The most important configuration variable is dovecot__dsync_host, which needs to be set to point to the other server for each server in a sync pair. Assuming that you have two servers, named mail1.example.com and mail2.example.com, setting something like this in your Ansible inventory should be sufficient:

dovecot__dsync_host: '{{ "mail1.example.com"
                         if ansible_fqdn == "mail2.example.com"
                         else "mail2.example.com" }}'

Other variables are dovecot__dsync_port, dovecot__dsync_replica, dovecot__dsync_password_path and dovecot__dsync_password, but these should all have sensible defaults for most installations.

For more information, see the Dovecot Replication <https://wiki.dovecot.org/Replication> wiki page.

  dovecot__user_accounts

Currently supported mechanisms for dovecot__user_accounts are:

deny
    Deny access for a statically defined list of users (see dovecot__deny_users).

system
    Mail users are Linux system users.

mysql
    Mail users are stored in a MySQL/MariaDB database (see SQL User Databases below).

pgsql
    Mail users are stored in a PostgreSQL database (see SQL User Databases below).

sqlite
    Mail users are stored in a SQLite database (see SQL User Databases below).

ldap
    Mail users are stored in the LDAP directory.

passwdfile
    Users and passwords are stored in a file.

checkpassword
    Users and passwords are stored in an external program.

  SQL User Databases

Users can be stored in an external SQL database (see dovecot__user_accounts above). In order to do so, a database-driver specific connection string needs to be defined in dovecot__sql_connect. The parameters are generally provided as a space-delimited string of parameter=value pairs (which means that it is not possible to use spaces in parameters), with the possible parameters defined by the used database type:

pgsql

host
    The host on which the database server is running.

port
    The port on which the database server is listening.

user
    The username to use when connecting to the database.

password
    The password to use when connecting to the database.

dbname
    The name of the database to use.

maxconns
    The number of connections to create to the database (default 5).

    mysql The basic options (host, port, user, password, dbname) are the same as for pgsql, additional settings include:

client_flags
    See the MySQL manual.

ssl_ca, ssl_ca_path
    Set either one or both to enable SSL.

ssl_cert, ssl_key
    For sending client-side certificates to the server.

ssl_cipher
    Sets the minimum allowed cipher security (default: HIGH).

ssl_verify_server_cert
    Verifies that the name in the server SSL certificate matches the host (default: no).

option_file
    Read options from the given file instead of the default my.cnf location.

option_group
    Read options from the given group (default: client).

    You can connect to UNIX sockets by using host=/var/run/mysql.sock.

sqlite
    Only one parameter is supported - the path to the database file (which is defined without the parameter=value format).

    Examples:

    # pgsql
    dovecot__sql_connect: 'host=192.168.1.1 dbname=users'
    # mysql
    dovecot__sql_connect: 'host=sql.example.com dbname=virtual user=virtual password=blarg'
    # sqlite
    dovecot__sql_connect: '/etc/dovecot/authdb.sqlite'

    The database should have a structure like this:

    CREATE TABLE `users` (
      `userid` varchar(128) NOT NULL,
      `domain` varchar(128) NOT NULL,
      `password` varchar(128) NOT NULL,
      `home` varchar(255) NOT NULL,
      `uid` int(11) NOT NULL,
      `gid` int(11) NOT NULL,
      `active` char(1) NOT NULL DEFAULT 'Y',
      `maildir` varchar(255) NOT NULL
    );

    Other configuration parameters of interest are dovecot__sql_default_pass_scheme, dovecot__sql_password_query, dovecot__sql_user_query, and dovecot__sql_iterate_query.

  dovecot__configuration

The dovecot__*_configuration variables define the contents of the /etc/dovecot/dovecot.conf configuration file. The variables are merged in the order defined by the dovecot__combined_configuration variable, which allows modification of the default configuration through the Ansible inventory.

See the dovecot configuration documentation <https://doc.dovecot.org/settings/> for details on the possible configuration parameters.

  Examples

See dovecot__default_configuration variable for an example of existing configuration.

Autosubscribe users to the Junk mailbox:

dovecot__group_configuration:
  - section: 'mailbox_namespaces'
    options:
      - name: 'namespace inbox'
        options:
          - name: 'mailbox Junk'
            options:
              - name: 'auto'
                value: 'subscribe'

Rename the Junk mailbox to INBOX.Spam:

dovecot__group_configuration:
  - section: 'mailbox_namespaces'
    options:
      - name: 'namespace inbox'
        options:
          - name: 'mailbox Junk'
            state: 'absent'
          - name: 'mailbox INBOX.Spam'
            options:
              - name: 'auto'
                value: 'subscribe'
              - name: 'special_use'
                value: '\Junk'

  Syntax

The variables contain a list of YAML dictionaries, each dictionary can have the following parameters:

section
    Required. Name of the section to create in the /etc/dovecot/dovecot.conf file. This parameter is used as an "anchor", configuration entries with the same section are combined together and affect each other in order of appearance.

title
    Optional. A short description of a given configuration section. If not defined, the section name itself will be used.

state
    Optional. If not specified or present, the configuration section will be generated. If hidden, the section will be generated, but without a section header. If absent, ignore or init, the configuration section will not be generated. If comment, the section will be generated but commented out.

weight
    Optional. A positive or negative number which can be used to affect the order of sections in the generated configuration file. Positive numbers add more "weight" to the section making it appear "lower" in the file; negative numbers subtract the "weight" and therefore move the section upper in the file.

comment
    Optional. This parameter can be used to provide a short description which will be included in the generated configuration file.

options
    Required. A list of dovecot configuration options for a given section.

    Note that the options parameters can be used recursively to generate configuration blocks of arbitrary depth (as illustrated in the example above).

    The options can be specified with the following parameters:

name
    Required. The name of a given dovecot configuration option for a given section. Options with the same section and name hierarchy will be merged in order of appearance.

option
    Optional. An alternative to name to be used as the key in the key = value pairs written to the configuration.

value
    Either value or options is required. This defines the value of a given configuration option. It can be either a string, a boolean, a number, or a YAML list (elements will be joined with commas).

options
    Either value or options is required. This parameters takes a list of configuration sub-options, thus allowing options to be used recursively to generate configuration blocks of arbitrary depth (as illustrated in the example above).

raw Optional. String or YAML text block which will be included in the configuration file "as is". If this parameter is specified, the name and value parameters are ignored - you need to specify the entire line(s) with configuration option names as well.

state
    Optional. Same values as documented above.

comment
    Optional. String or YAML text block that contains comments about a given configuration option.

AUTHOR
Reto Gantenbein, Maciej Delmanowski, David Härdeman

COPYRIGHT
2014-2024, Maciej Delmanowski, Nick Janetakis, Robin Schneider and others