~nka/ansible-role-dovecot

7715c63befe5539ebcef090b3ec88784f7920715 — Nicolas KAROLAK 2 months ago v1.0.0
init
A  => defaults/main.yml +25 -0
@@ 1,25 @@
---

imap_packages:
  - dovecot-imapd
  - dovecot-lmtpd
  - dovecot-managesieved
  - dovecot-pgsql

imap_protocols:
  - imap
  - lmtp
  - sieve

imap_db_host: localhost
imap_db_port: 5432
imap_db_user: postfix
imap_db_password:
imap_db_name: postfix

imap_postmaster: postmaster@example.net

imap_tls_cert: /etc/ssl/certs/ssl-cert-snakeoil.pem
imap_tls_key: /etc/ssl/certs/ssl-cert-snakeoil.key

...

A  => handlers/main.yml +26 -0
@@ 1,26 @@
---

- name: compile check spam script
  become: true
  become_user: vmail
  command:
    cmd: sievec /var/mail/vhosts/sieve/global/check-spam.sieve

- name: compile learn spam script
  become: true
  become_user: vmail
  command:
    cmd: sievec /var/mail/vhosts/sieve/global/report-spam.sieve

- name: compile learn ham script
  become: true
  become_user: vmail
  command:
    cmd: sievec /var/mail/vhosts/sieve/global/report-ham.sieve

- name: restart imap server
  systemd:
    name: dovecot
    state: restarted

...

A  => meta/main.yml +14 -0
@@ 1,14 @@
---

galaxy_info:
  author: Nicolas Karolak
  description: Install and configure a Dovecot server
  galaxy_tags: []
  license: WTFPL
  min_ansible_version: 2.9
  platforms:
    - name: 'Debian'
      versions:
        - 'buster'

dependencies: []

A  => tasks/main.yml +116 -0
@@ 1,116 @@
---

- name: install packages
  apt:
    force_apt_get: true
    install_recommends: false
    name: "{{ imap_packages }}"

- name: create vmail group
  register: imap_group
  group:
    name: vmail
    system: yes

- name: create vmail user
  register: imap_user
  user:
    name: vmail
    group: vmail
    comment: Virtual Mail Handler
    home: /var/mail/vhosts
    shell: /usr/sbin/nologin
    system: yes

- name: create vmail directories
  loop:
    - /var/mail/vhosts
    - /var/mail/vhosts/sieve
    - /var/mail/vhosts/sieve/global
    - /var/mail/attachments
  file:
    path: "{{ item }}"
    owner: vmail
    group: vmail
    mode: 0770
    state: directory

- name: configure imap server
  notify: restart imap server
  loop:
    - conf.d/10-auth.conf
    - conf.d/10-mail.conf
    - conf.d/10-master.conf
    - conf.d/10-ssl.conf
    - conf.d/15-mailboxes.conf
    - conf.d/20-imap.conf
    - conf.d/20-lmtp.conf
    - conf.d/20-managesieve.conf
    - conf.d/90-quota.conf
    - conf.d/90-sieve.conf
    - dovecot-dict-sql.conf.ext
    - dovecot-sql.conf.ext
    - dovecot.conf
  template:
    src: "{{ item }}.j2"
    dest: /etc/dovecot/{{ item }}

- name: quota warning script
  template:
    src: quota-warning.sh.j2
    dest: /etc/dovecot/quota-warning.sh
    mode: 0755

- name: global check spam sieve script
  notify: compile check spam script
  copy:
    dest: /var/mail/vhosts/sieve/global/check-spam.sieve
    owner: vmail
    group: vmail
    content: |
      require ["fileinto","mailbox"];

      if anyof(
          header :contains ["X-Spam-Flag"] "YES",
          header :contains ["X-Spam"] "Yes",
          header :contains ["Subject"] "*** SPAM ***"
          )
      {
          fileinto :create "Junk";
          stop;
      }

- name: global learn spam sieve script
  notify: compile learn spam script
  copy:
    dest: /var/mail/vhosts/sieve/global/report-spam.sieve
    owner: vmail
    group: vmail
    content: |
      require ["vnd.dovecot.pipe", "copy", "imapsieve"];
      pipe :copy "rspamc" ["learn_spam"];

- name: global learn ham sieve script
  notify: compile learn ham script
  copy:
    dest: /var/mail/vhosts/sieve/global/report-ham.sieve
    owner: vmail
    group: vmail
    content: |
      require ["vnd.dovecot.pipe", "copy", "imapsieve"];
      pipe :copy "rspamc" ["learn_ham"];

- name: update certificates links
  notify: restart imap server
  loop:
    - link: /etc/dovecot/private/dovecot.key
      source: "{{ imap_tls_key }}"
    - link: /etc/dovecot/private/dovecot.pem
      source: "{{ imap_tls_cert }}"
  file:
    src: "{{ item.source }}"
    dest: "{{ item.link }}"
    force: true
    state: link

...

A  => templates/conf.d/10-auth.conf.j2 +16 -0
@@ 1,16 @@
auth_cache_size = 10M
auth_cache_ttl = 1 hour
auth_cache_negative_ttl = 1 hour

disable_plaintext_auth = yes
auth_mechanisms = plain login

passdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

userdb {
  driver = sql
  args = /etc/dovecot/dovecot-sql.conf.ext
}

A  => templates/conf.d/10-mail.conf.j2 +21 -0
@@ 1,21 @@
mail_uid = {{ imap_user.name }}
first_valid_uid = {{ imap_user.uid }}
last_valid_uid = {{ imap_user.uid }}

mail_gid = {{ imap_group.name }}
first_valid_gid = {{ imap_group.gid }}
last_valid_gid = {{ imap_group.gid }}

mail_location = mdbox:~/mdbox

namespace inbox {
  separator = /
  inbox = yes
}

mail_privileged_group = {{ imap_group.name }}

mail_attachment_dir = /var/mail/attachments
mail_attachment_min_size = 64k

mail_plugins = quota

A  => templates/conf.d/10-master.conf.j2 +39 -0
@@ 1,39 @@
service imap-login {
	inet_listener imap {
		port = 0
	}
	inet_listener imaps {
	}
}
service pop3-login {
	inet_listener pop3 {
		port = 0
	}
	inet_listener pop3s {
		port = 0
	}
}
service imap {
}
service lmtp {
	inet_listener ltmp {
		address = 0.0.0.0 ::0
		port = 24
	}
}
service auth {
	inet_listener {
		address = 0.0.0.0 ::0
		port = 1993
	}
}
service auth-worker {
	user = {{ imap_user.name }}
}
service dict {
	unix_listener dict {
		mode = 0660
		user = {{ imap_user.name }}
		group = {{ imap_group.name }}
	}
}

A  => templates/conf.d/10-ssl.conf.j2 +4 -0
@@ 1,4 @@
ssl = required
ssl_cert = </etc/dovecot/private/dovecot.pem
ssl_key = </etc/dovecot/private/dovecot.key
ssl_dh = </usr/share/dovecot/dh.pem

A  => templates/conf.d/15-mailboxes.conf.j2 +26 -0
@@ 1,26 @@
namespace inbox {
	mailbox Drafts {
		auto = subscribe
		special_use = \Drafts
	}
	mailbox Junk {
		auto = subscribe
		special_use = \Junk
	}
	mailbox Trash {
		auto = subscribe
		special_use = \Trash
	}
	mailbox Archive {
		auto = subscribe
		special_use = \Archive
	}
	mailbox Sent {
		auto = subscribe
		special_use = \Sent
	}
	mailbox virtual/Flagged {
		auto = subscribe
		special_use = \Flagged
	}
}

A  => templates/conf.d/20-imap.conf.j2 +4 -0
@@ 1,4 @@
imap_idle_notify_interval = 25 mins
protocol imap {
	mail_plugins = $mail_plugins imap_quota imap_sieve
}

A  => templates/conf.d/20-lmtp.conf.j2 +3 -0
@@ 1,3 @@
protocol lmtp {
	mail_plugins = $mail_plugins sieve
}

A  => templates/conf.d/20-managesieve.conf.j2 +12 -0
@@ 1,12 @@
service managesieve-login {
	inet_listener sieve {
		port = 4190
	}
}

service managesieve {
	process_limit = 1024
}

protocol sieve {
}

A  => templates/conf.d/90-quota.conf.j2 +26 -0
@@ 1,26 @@
plugin {
	quota = dict:User quota::proxy::sqlquota
	quota_rule = *:storage=5GB
	quota_rule2 = Trash:storage=+100M
	quota_grace = 10%%
	quota_exceeded_message = Quota exceeded, please contact your system administrator.
	quota_warning = storage=100%% quota-warning 100 %u
	quota_warning2 = storage=95%% quota-warning 95 %u
	quota_warning3 = storage=90%% quota-warning 90 %u
	quota_warning4 = storage=85%% quota-warning 85 %u
}

service quota-warning {
	executable = script /etc/dovecot/quota-warning.sh
	user = {{ imap_user.name }}

	unix_listener quota-warning {
		mode = 0660
		user = {{ imap_user.name }}
		group = {{ imap_group.name }}
	}
}

dict {
	sqlquota = pgsql:/etc/dovecot/dovecot-dict-sql.conf.ext
}

A  => templates/conf.d/90-sieve.conf.j2 +19 -0
@@ 1,19 @@
plugin {
  sieve_plugins = sieve_imapsieve sieve_extprograms
  sieve_before = /var/mail/vhosts/sieve/global/check-spam.sieve
  sieve = file:/var/mail/vhosts/sieve/%d/%n/scripts;active=/var/mail/vhosts/sieve/%d/%n/active-script.sieve

  imapsieve_mailbox1_name = Junk
  imapsieve_mailbox1_causes = COPY
  imapsieve_mailbox1_before = file:/var/mail/vhosts/sieve/global/report-spam.sieve

  imapsieve_mailbox2_name = *
  imapsieve_mailbox2_from = Junk
  imapsieve_mailbox2_causes = COPY
  imapsieve_mailbox2_before = file:/var/mail/vhosts/sieve/global/report-ham.sieve

  sieve_pipe_bin_dir = /usr/bin
  sieve_global_extensions = +vnd.dovecot.pipe

  recipient_delimiter = +
}

A  => templates/dovecot-dict-sql.conf.ext.j2 +15 -0
@@ 1,15 @@
connect = host={{ imap_db_host }} port={{ imap_db_port }} dbname={{ imap_db_name }} user={{ imap_db_user }} password={{ imap_db_password }}

map {
	pattern = priv/quota/storage
	table = quota2
	username_field = username
	value_field = bytes
}

map {
	pattern = priv/quota/messages
	table = quota2
	username_field = username
	value_field = messages
}

A  => templates/dovecot-sql.conf.ext.j2 +20 -0
@@ 1,20 @@
driver = pgsql
connect = host={{ imap_db_host }} port={{ imap_db_port }} dbname={{ imap_db_name }} user={{ imap_db_user }} password={{ imap_db_password }}
default_pass_scheme = MD5-CRYPT
iterate_query = SELECT username AS user FROM mailbox
user_query = \
	SELECT \
		CONCAT('/var/mail/vhosts/', maildir) AS home, \
		CONCAT('*:bytes=', quota) AS quota_rule \
	FROM mailbox \
	WHERE \
		username = '%u' \
		AND active = '1'
password_query = \
	SELECT \
		username AS user, \
		password \
	FROM mailbox \
	WHERE \
		username = '%u' \
		AND active = '1'

A  => templates/dovecot.conf.j2 +4 -0
@@ 1,4 @@
protocols = {{ imap_protocols | join(' ') }}

!include conf.d/*.conf
!include_try local.conf

A  => templates/quota-warning.sh.j2 +9 -0
@@ 1,9 @@
#!/bin/sh
PERCENT=$1
USER=$2
cat << EOF | /usr/lib/dovecot/dovecot-lda -d $USER -o "plugin/quota=dict:User quota::noenforcing:proxy::sqlquota"
From: {{ imap_postmaster }}
Subject: Quota warning

Your mailbox is now $PERCENT% full.
EOF