Add a Dovecot role

Changes #10
This commit is contained in:
genofire 2020-10-21 16:18:30 +02:00
parent 4dfd89dff1
commit 372f5265d7
12 changed files with 448 additions and 0 deletions

View File

@ -1,4 +1,6 @@
--- ---
dovecot_listen: '[2a01:4f8:150:926f::2], 176.9.59.104'
haproxy_v4: 176.9.59.104 haproxy_v4: 176.9.59.104
haproxy_v6: 2a01:4f8:150:926f::2 haproxy_v6: 2a01:4f8:150:926f::2

View File

@ -0,0 +1,14 @@
---
- name: Reload s6-rc
service:
name: s6-rc
state: reloaded
- name: Reload Dovecot
command: s6-svc -h /run/service/dovecot
- name: Restart Dovecot
command: s6-svc -wR -T 5000 /run/service/dovecot
- name: Restart Dovecot log
command: s6-svc -wR -T 5000 /run/service/dovecot-log

View File

@ -0,0 +1,161 @@
---
- name: Install Dovecot
package:
name: dovecot dovecot-fts-xapian dovecot-pigeonhole
state: present
- name: Set permissions on /usr/local/etc/dovecot
file:
path: /usr/local/etc/dovecot
state: directory
owner: acme
group: dovecot
mode: 0750
- name: Generate DH parameters
command: openssl dhparam -out /usr/local/etc/dovecot/dh.pem 2048
args:
creates: /usr/local/etc/dovecot/dh.pem
- name: Add vmail group
group:
name: vmail
gid: 20002
- name: Add vmail user
user:
name: vmail
uid: 20002
group: vmail
home: /var/empty
create_home: no
login_class: daemon
password: '*'
- name: Add vmail ZFS file system
zfs:
name: '{{ bhyve_pool }}/var/vmail'
state: present
- name: Set permissions on /var/vmail
file:
path: /var/vmail
state: directory
owner: vmail
group: vmail
mode: 0750
- name: Create /var/spool/postfix
file:
path: /var/spool/postfix
state: directory
owner: root
group: wheel
mode: 0755
- name: Add /var/log/dovecot to fstab
mount:
path: /var/log/dovecot
src: tmpfs
fstype: tmpfs
opts: 'rw,size={{ dovecot_log_size }},mode={{ dovecot_log_mode }},uid={{ dovecot_log_uid }},gid={{ dovecot_log_gid }},late'
state: mounted
- name: Create Dovecot service directories
file:
path: '/etc/s6-rc/service/{{ item }}'
state: directory
owner: root
group: wheel
mode: 0755
with_items: '{{ dovecot_service_dirs }}'
notify:
- Reload s6-rc
- Restart Dovecot log
- Restart Dovecot
- name: Generate Dovecot service scripts
template:
dest: '/etc/s6-rc/service/{{ item }}'
src: '{{ item }}.j2'
mode: 0555
owner: root
group: wheel
with_items: '{{ dovecot_service_scripts }}'
notify:
- Reload s6-rc
- Restart Dovecot log
- Restart Dovecot
- name: Generate Dovecot service configuration
copy:
dest: '/etc/s6-rc/service/{{ item.name }}'
content: '{{ item.content }}'
mode: 0444
owner: root
group: wheel
loop_control:
label: '{{ item.name }} = {{ item.content }}'
notify:
- Reload s6-rc
- Restart Dovecot log
- Restart Dovecot
with_items: '{{ dovecot_service_config }}'
- name: Configure dovecot
template:
dest: '/usr/local/etc/dovecot/{{ item }}'
src: '{{ item }}.j2'
mode: 0440
owner: dovecot
group: wheel
with_items:
- dovecot.conf
- passwd
notify:
- Reload Dovecot
- name: Tell acme.sh where to find Dovecot
lineinfile:
path: /var/db/acme/account.conf
create: yes
owner: acme
group: acme
regexp: '^DEPLOY_DOVECOT_PEM_PATH='
state: present
line: 'DEPLOY_DOVECOT_RELOAD="sudo s6-svc -h /run/service/dovecot"'
- name: Flush handlers
meta: flush_handlers
- name: Allow acme.sh to reload Dovecot
template:
dest: /usr/local/etc/sudoers.d/acme_dovecot
src: acme_dovecot.j2
mode: 0444
owner: root
group: wheel
- name: Deploy X.509 certificate to Dovecot
command: 'env sudo -Hu acme acme.sh --debug --home /var/db/acme --install-cert --domain {{ ansible_fqdn }} --cert-file /usr/local/etc/dovecot/cert.pem --key-file /usr/local/etc/dovecot/privkey.pem --fullchain-file /usr/local/etc/dovecot/fullchain.pem --reloadcmd "sudo s6-svc -h /run/service/dovecot"'
args:
creates: /usr/local/etc/dovecot/fullchain.pem
notify:
- Reload Dovecot
- name: Start Dovecot
command: fdmove -c 2 1 s6-rc -u -v 2 -t 15000 change dovecot
register: change
changed_when: change.stdout | length > 0
- name: Enable Dovecot
lineinfile:
path: /etc/s6-rc/service/enabled/contents
regexp: "^dovecot$"
line: dovecot
state: present
notify:
- Reload s6-rc
- name: Flush handlers (again)
meta: flush_handlers

View File

@ -0,0 +1 @@
acme ALL=NOPASSWD:/usr/local/bin/s6-svc -h /run/service/dovecot

View File

@ -0,0 +1,13 @@
#!/usr/local/bin/execlineb -S2
# {{ ansible_managed }}
s6-envdir ./env
multisubstitute {
importas -i -u NAME NAME
}
fdmove -c 1 2
ifelse { test "${1}" -eq 0 } {
echo "${NAME}-log: Stopped."
}
echo "${NAME}-log: Failed with exit status (${1}, ${2})."

View File

@ -0,0 +1,23 @@
#!/usr/local/bin/execlineb
# {{ ansible_managed }}
s6-envdir ./env
multisubstitute {
importas -i -u NAME NAME
importas -i -u USER USER
importas -i -u GROUP GROUP
importas -i -u MODE MODE
importas -i -u DIR DIR
}
foreground { fdmove -c 1 2 echo "${NAME} log: Starting." }
ifelse -n { install -d -o "${USER}" -g "${GROUP}" -m "${MODE}" "$DIR" } {
foreground { fdmove -c 1 2 echo "${NAME} log: Failed to create logging directory." }
false
}
fdmove -c 2 1
s6-envuidgid $USER
s6-log -d 3 T $DIR

View File

@ -0,0 +1,124 @@
# {{ ansible_managed }}
base_dir = /var/run/dovecot
import_environment = TZ LC_CTYPE LC_TIME LC_COLLATE LC_NUMERIC LC_MONETARY
log_path = /dev/stderr
default_vsz_limit = 2 G
verbose_proctitle = yes
doveadm_worker_count = 8
mail_location = mdbox:~/mdbox
mail_plugins = fts fts_xapian
listen = {{ dovecot_listen }}
ssl = required
ssl_cert = </usr/local/etc/dovecot/fullchain.pem
ssl_key = </usr/local/etc/dovecot/privkey.pem
ssl_cipher_list = 'EDH+CAMELLIA:EDH+aRSA:EECDH+aRSA+AESGCM:EECDH+aRSA+SHA256:EECDH:+CAMELLIA128:+AES128:+SSLv3:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!DSS:!RC4:!SEED:!IDEA:!ECDSA:kEDH:CAMELLIA128-SHA:AES128-SHA'
ssl_prefer_server_ciphers = yes
ssl_options = no_compression
ssl_dh = </usr/local/etc/dovecot/dh.pem
plugin {
fts = xapian
fts_xapian = partial=3 full=20 attachments=0 verbose=0
fts_autoindex = yes
fts_enforced = yes
fts_autoindex_exclude = \Trash
}
plugin {
sieve = ~/.dovecot.sieve
sieve_dir = ~/sieve
sieve_extensions = +vacation-seconds
sieve_vacation_min_period = 1d
sieve_vacation_default_period = 1d
sieve_vacation_max_period = 30d
}
namespace inbox {
inbox = yes
mailbox Drafts {
special_use = \Drafts
auto = subscribe
}
mailbox Junk {
special_use = \Junk
auto = subscribe
}
mailbox Sent {
special_use = \Sent
auto = subscribe
}
mailbox Trash {
special_use = \Trash
auto = subscribe
}
}
passdb {
driver = passwd-file
args = /usr/local/etc/dovecot/passwd
}
userdb {
driver = passwd-file
args = /usr/local/etc/dovecot/passwd
default_fields = uid=vmail gid=vmail home=/var/vmail/%d/%n
}
protocols = imap lmtp sieve
auth_mechanisms = plain login
auth_default_realm = %{hostname}
service auth {
unix_listener /var/spool/postfix/private/dovecot-auth {
user = postfix
group = postfix
mode = 0600
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
user = postfix
group = postfix
mode = 0600
}
}
service managesieve-login {
inet_listener sieve {
port = 4190
}
inet_listener sieve_deprecated {
port = 2000
}
service_count = 1
}
service imap-login {
inet_listener imap {
port = 143
}
inet_listener imaps {
port = 993
ssl = yes
}
process_limit = 128
}
protocol lmtp {
mail_plugins = $mail_plugins sieve
}

View File

@ -0,0 +1,18 @@
#!/usr/local/bin/execlineb -P
# {{ ansible_managed }}
s6-envdir ./env
multisubstitute {
importas -i -u NAME NAME
}
ifelse {
redirfd -w 1 /dev/null
fdmove -c 2 1
doveadm who
} {
foreground { fdmove -c 1 2 echo "${NAME}: Ready." }
true
}
foreground { fdmove -c 1 2 echo "${NAME}: Poll." }
false

View File

@ -0,0 +1,13 @@
#!/usr/local/bin/execlineb -S2
# {{ ansible_managed }}
s6-envdir ./env
multisubstitute {
importas -i -u NAME NAME
}
fdmove -c 1 2
ifelse { test "${1}" -eq 0 } {
echo "${NAME}: Stopped."
}
echo "${NAME}: Failed with exit status (${1}, ${2})."

View File

@ -0,0 +1,13 @@
#!/usr/local/bin/execlineb -P
# {{ ansible_managed }}
s6-envdir ./env
multisubstitute {
importas -i -u NAME NAME
}
foreground { fdmove -c 1 2 echo "${NAME}: Starting." }
s6-notifyoncheck -d -w 100 -n 70
fdmove -c 2 1
dovecot -F

View File

@ -0,0 +1,5 @@
{% for domain, users in dovecot_users.items() %}
{% for name, password in users.items() %}
{{ [[name, domain] | join("@"), password, 20002, 20002, ["/var/vmail", domain, name] | join("/"), ""] | join(":") }}
{% endfor %}
{% endfor %}

View File

@ -0,0 +1,61 @@
---
dovecot_log_size: '32m'
dovecot_log_mode: '750'
dovecot_log_uid: '20000'
dovecot_log_gid: '20000'
dovecot_service_dirs:
- dovecot
- dovecot/env
- dovecot/data
- dovecot-log
- dovecot-log/env
dovecot_service_scripts:
- dovecot/run
- dovecot/finish
- dovecot/data/check
- dovecot-log/run
- dovecot-log/finish
dovecot_service_config:
- name: dovecot/type
content: longrun
- name: dovecot/producer-for
content: dovecot-log
- name: dovecot/notification-fd
content: 3
- name: dovecot/env/NAME
content: dovecot
- name: dovecot/env/PATH
content: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
- name: dovecot-log/type
content: longrun
- name: dovecot-log/notification-fd
content: 3
- name: dovecot-log/consumer-for
content: dovecot
- name: dovecot-log/env/NAME
content: dovecot
- name: dovecot-log/env/PATH
content: /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin
- name: dovecot-log/env/MODE
content: '750'
- name: dovecot-log/env/USER
content: s6-log
- name: dovecot-log/env/GROUP
content: s6-log
- name: dovecot-log/env/DIR
content: /var/log/dovecot
dovecot_config:
- name: maillog_file
value: /var/log/dovecot/fifo
state: present
- name: inet_protocols
value: '{{ dovecot_inet_protocols | default("ipv6, ipv4") }}'
state: present
- name: inet_interfaces
value: '{{ dovecot_inet_interfaces }}'
state: present