summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorclarkzjw <[email protected]>2023-02-08 00:40:09 -0800
committerclarkzjw <[email protected]>2023-02-08 00:40:09 -0800
commit1204730924436ef9e1c7c49c9557837f9a5ed0e8 (patch)
tree129d79dfd11245751cee6d4082ff5d2f6e941610 /ansible/roles/dovecot
parent9635ac4dedf69de5bff65785bcc16bef80b52d75 (diff)
downloadmail-1204730924436ef9e1c7c49c9557837f9a5ed0e8.tar.gz
fork https://github.com/mattsta/mailwebHEADmaster
Diffstat (limited to 'ansible/roles/dovecot')
-rw-r--r--ansible/roles/dovecot/files/dovecot/authdb.sqlite3.emptybin0 -> 2048 bytes
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/10-acl.conf15
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/10-auth.conf46
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/10-mail.conf28
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/10-master.conf82
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/15-lda.conf7
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/15-mailboxes.conf24
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/20-imap.conf10
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/20-lmtp.conf5
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/90-imapsieve.conf18
-rw-r--r--ansible/roles/dovecot/files/dovecot/conf.d/90-sieve.conf34
-rw-r--r--ansible/roles/dovecot/files/dovecot/dovecot-sql.conf.ext150
-rw-r--r--ansible/roles/dovecot/files/dovecot/dovecot.conf19
-rw-r--r--ansible/roles/dovecot/files/dovecot/sieve-before.d/10-rspamd.sieve5
-rw-r--r--ansible/roles/dovecot/files/dovecot/sieve/report-ham.sieve23
-rw-r--r--ansible/roles/dovecot/files/dovecot/sieve/report-spam.sieve7
-rwxr-xr-xansible/roles/dovecot/files/dovecot/sieve/train-ham.sh1
-rwxr-xr-xansible/roles/dovecot/files/dovecot/sieve/train-spam.sh1
-rw-r--r--ansible/roles/dovecot/handlers/main.yml31
-rw-r--r--ansible/roles/dovecot/tasks/main.yml110
-rw-r--r--ansible/roles/dovecot/templates/dovecot/conf.d/10-ssl.conf.j222
21 files changed, 638 insertions, 0 deletions
diff --git a/ansible/roles/dovecot/files/dovecot/authdb.sqlite3.empty b/ansible/roles/dovecot/files/dovecot/authdb.sqlite3.empty
new file mode 100644
index 0000000..f1e0330
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/authdb.sqlite3.empty
Binary files differ
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/10-acl.conf b/ansible/roles/dovecot/files/dovecot/conf.d/10-acl.conf
new file mode 100644
index 0000000..f9fa335
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/10-acl.conf
@@ -0,0 +1,15 @@
1mail_plugins = $mail_plugins acl
2
3protocol imap {
4 mail_plugins = $mail_plugins imap_acl
5}
6
7plugin {
8 acl_defaults_from_inbox = yes
9}
10
11# Should saving a mail to a nonexistent mailbox automatically create it?
12lda_mailbox_autocreate = yes
13
14# Should automatically created mailboxes be also automatically subscribed?
15lda_mailbox_autosubscribe = yes
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/10-auth.conf b/ansible/roles/dovecot/files/dovecot/conf.d/10-auth.conf
new file mode 100644
index 0000000..4e23fa8
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/10-auth.conf
@@ -0,0 +1,46 @@
1# cache all authentication results for one hour
2#auth_cache_size = 10M
3#auth_cache_ttl = 1 hour
4#auth_cache_negative_ttl = 1 hour
5
6# Don't cache password details, otherwise password changes require a server HUP
7# before the server will re-query the password data source.
8auth_cache_size = 0
9
10# only use plain username/password auth - OK since everything is over TLS
11auth_mechanisms = plain
12
13# passdb specifies how users are authenticated - sql here, and
14# our sql config specifies the sqlite filename with queries to use
15passdb {
16 driver = sql
17 args = /etc/dovecot/dovecot-sql.conf.ext
18}
19
20# userdb specifies the location of users' "home" directories - where their
21# mail is stored. e.g. /var/mail/vhosts/exmaple.com/user
22# %d = domain, %n = user
23# We can't use "prefetch" because postfix can't read users from "prefetch" db,
24# and we can't use 'static' because the doveadm tool needs to iterate users
25# for purging zero refcount deleted mails, so we give a userdb of sql here
26# and specify a "get all users" SQL query in the configuration file.
27userdb {
28 driver = sql
29 args = /etc/dovecot/dovecot-sql.conf.ext
30}
31
32# UNIX socket path to master authentication server to find users.
33# This is used by imap (for shared users) and lda.
34auth_socket_path = /var/run/dovecot/auth-userdb
35
36# Respect /etc/hosts.deny (populated by fail2ban)
37# You can use /etc/hosts.allow to countermand fail2ban decisions.
38login_access_sockets = tcpwrap
39
40service tcpwrap {
41 unix_listener login/tcpwrap {
42 group = $default_login_user
43 mode = 0600
44 user = $default_login_user
45 }
46}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/10-mail.conf b/ansible/roles/dovecot/files/dovecot/conf.d/10-mail.conf
new file mode 100644
index 0000000..6c03965
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/10-mail.conf
@@ -0,0 +1,28 @@
1# default home directory location for all users
2mail_home = /var/mail/vhosts/%d/%n
3
4# directory to store mail. The tilda makes it relative to the *dovecot*
5# virtual home directory.
6#
7# I use mdbox - this is Dovecot's own high-performance mail store format.
8# There are other slower, more "traditional" formats you can choose from.
9# Read about them here: https://wiki2.dovecot.org/MailboxFormat
10mail_location = mdbox:~/mdbox
11
12# nothing fancy - just a standard default namespace with '/' as the
13# hierarchy separator
14namespace inbox {
15 separator = /
16 inbox = yes
17}
18
19# set this to the group that owns your vmail directory.
20mail_privileged_group = vmail
21
22# these lines enable attachment deduplication. Attachments must be somewhat
23# large (64k) to store them separately from the mail store.
24mail_attachment_dir = /var/mail/attachments
25mail_attachment_min_size = 64k
26
27# we'll uncomment this after we set up Solr in the following section:
28# mail_plugins = $mail_plugins fts fts_solr
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/10-master.conf b/ansible/roles/dovecot/files/dovecot/conf.d/10-master.conf
new file mode 100644
index 0000000..f99d0f4
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/10-master.conf
@@ -0,0 +1,82 @@
1# to improve performance, disable fsync globally - we will enable it for
2# some specific services later on
3mail_fsync = never
4
5service imap-login {
6 # plain-text IMAP should only be accessible from localhost
7 inet_listener imap {
8 address = 127.0.0.1, ::1
9 }
10
11 # enable high-performance mode, described here:
12 # https://wiki.dovecot.org/LoginProcess
13 service_count = 0
14
15 # set to the number of CPU cores on your server
16 process_min_avail = 3
17 vsz_limit = 1G
18}
19
20# disable POP3 altogether
21service pop3-login {
22 inet_listener pop3 {
23 port = 0
24 }
25
26 inet_listener pop3s {
27 port = 0
28 }
29}
30
31# enable semi-long-lived IMAP processes to improve performance
32service imap {
33 service_count = 256
34 # set to the number of CPU cores on your server
35 process_min_avail = 3
36}
37
38# expose an LMTP socket for postfix to deliver mail
39service lmtp {
40 unix_listener /var/spool/postfix/private/dovecot-lmtp {
41 group = postfix
42 mode = 0600
43 user = postfix
44 }
45}
46
47service auth {
48 # auth_socket_path points to this userdb socket by default. It's typically
49 # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
50 # full permissions to this socket are able to get a list of all usernames and
51 # get the results of everyone's userdb lookups.
52 #
53 # The default 0666 mode allows anyone to connect to the socket, but the
54 # userdb lookups will succeed only if the userdb returns an "uid" field that
55 # matches the caller process's UID. Also if caller's uid or gid matches the
56 # socket's uid or gid the lookup succeeds. Anything else causes a failure.
57 #
58 # To give the caller full permissions to lookup all users, set the mode to
59 # something else than 0666 and Dovecot lets the kernel enforce the
60 # permissions (e.g. 0777 allows everyone full permissions).
61
62 # auth for postfix
63 unix_listener /var/spool/postfix/private/auth {
64 mode = 0666
65 user = postfix
66 group = postfix
67 }
68
69 # auth for doveadm tools
70 unix_listener auth-userdb {
71 mode = 0666
72 user = vmail
73 group = vmail
74 }
75
76 client_limit = 840
77}
78
79# no need to run this as root
80service auth-worker {
81 user = vmail
82}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/15-lda.conf b/ansible/roles/dovecot/files/dovecot/conf.d/15-lda.conf
new file mode 100644
index 0000000..32ca50d
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/15-lda.conf
@@ -0,0 +1,7 @@
1# configuration for mail delivered by the `dovecot-lda` command. Shouldn't
2# be needed since we are using LMTP, but kept for backwards compatibility.
3protocol lda {
4 # use fsync for write-safety - this deals with delivering actual mail
5 mail_fsync = optimized
6 mail_plugins = $mail_plugins sieve
7}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/15-mailboxes.conf b/ansible/roles/dovecot/files/dovecot/conf.d/15-mailboxes.conf
new file mode 100644
index 0000000..8674b0b
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/15-mailboxes.conf
@@ -0,0 +1,24 @@
1# define any special IMAP folders here. You can force them to be created or
2# created+subscribed automatically used the `auto` option.
3namespace inbox {
4 mailbox Drafts {
5 auto = subscribe
6 special_use = \Drafts
7 }
8 mailbox Junk {
9 auto = create
10 special_use = \Junk
11 }
12 mailbox Trash {
13 auto = create
14 special_use = \Trash
15 }
16 mailbox Archive {
17 auto = subscribe
18 special_use = \Archive
19 }
20 mailbox Sent {
21 auto = subscribe
22 special_use = \Sent
23 }
24}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/20-imap.conf b/ansible/roles/dovecot/files/dovecot/conf.d/20-imap.conf
new file mode 100644
index 0000000..7b32396
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/20-imap.conf
@@ -0,0 +1,10 @@
1# Use a longer IDLE interval to reduce network chatter and save battery
2# life. Max is 30 minutes.
3imap_idle_notify_interval = 29 mins
4
5protocol imap {
6 # max IMAP connections per IP address
7 mail_max_userip_connections = 50
8 # imap_sieve will be used for spam training by rspamd
9 mail_plugins = $mail_plugins imap_sieve
10}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/20-lmtp.conf b/ansible/roles/dovecot/files/dovecot/conf.d/20-lmtp.conf
new file mode 100644
index 0000000..a51ee42
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/20-lmtp.conf
@@ -0,0 +1,5 @@
1protocol lmtp {
2 # use fsync for write-safety - this deals with delivering actual mail
3 mail_fsync = optimized
4 mail_plugins = $mail_plugins sieve
5}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/90-imapsieve.conf b/ansible/roles/dovecot/files/dovecot/conf.d/90-imapsieve.conf
new file mode 100644
index 0000000..26987b1
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/90-imapsieve.conf
@@ -0,0 +1,18 @@
1plugin {
2 sieve_plugins = sieve_imapsieve sieve_extprograms
3
4 # From elsewhere to Junk folder
5 imapsieve_mailbox1_name = Junk
6 imapsieve_mailbox1_causes = COPY
7 imapsieve_mailbox1_before = file:/etc/dovecot/sieve/report-spam.sieve
8
9 # From Junk folder to elsewhere
10 imapsieve_mailbox2_name = *
11 imapsieve_mailbox2_from = Junk
12 imapsieve_mailbox2_causes = COPY
13 imapsieve_mailbox2_before = file:/etc/dovecot/sieve/report-ham.sieve
14
15 sieve_pipe_bin_dir = /etc/dovecot/sieve
16
17 sieve_global_extensions = +vnd.dovecot.pipe
18}
diff --git a/ansible/roles/dovecot/files/dovecot/conf.d/90-sieve.conf b/ansible/roles/dovecot/files/dovecot/conf.d/90-sieve.conf
new file mode 100644
index 0000000..9a753bf
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/conf.d/90-sieve.conf
@@ -0,0 +1,34 @@
1plugin {
2 # 'active' is a symlink to one sieve source script inside directory at 'file'
3 sieve = file:~/sieve;active=~/.dovecot.sieve
4
5 # directory of global sieve scripts to run before and after processing ALL
6 # incoming mail
7 sieve_before = /etc/dovecot/sieve-before.d
8 sieve_after = /etc/dovecot/sieve-after.d
9
10 # make sieve aware of [email protected] aliases
11 recipient_delimiter = +
12
13
14 # no limits on script size or actions
15 sieve_quota_max_storage = 0
16 sieve_max_script_size = 0
17 sieve_max_actions = 0
18
19 sieve_extensions = +spamtest +spamtestplus
20
21 sieve_spamtest_status_header = X-Spam-Score
22 sieve_spamtest_status_type = strlen
23
24 # X-Spamd-Bar: +++++++++
25 sieve_spamtest_max_value = 9
26
27
28 # X-Spamd-Result: default: False [9.19 / 15.00];
29 # (regex not fixed to capture the above)
30 #sieve_spamtest_status_type = score
31 #sieve_spamtest_status_header = \
32 # X-Spamd-Result: [[:alnum:]]+, score=(-?[[:digit:]]+\.[[:digit:]])
33 #sieve_spamtest_max_value = 5.0
34}
diff --git a/ansible/roles/dovecot/files/dovecot/dovecot-sql.conf.ext b/ansible/roles/dovecot/files/dovecot/dovecot-sql.conf.ext
new file mode 100644
index 0000000..f248243
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/dovecot-sql.conf.ext
@@ -0,0 +1,150 @@
1# This file is commonly accessed via passdb {} or userdb {} section in
2# conf.d/auth-sql.conf.ext
3
4# This file is opened as root, so it should be owned by root and mode 0600.
5#
6# http://wiki2.dovecot.org/AuthDatabase/SQL
7#
8# For the sql passdb module, you'll need a database with a table that
9# contains fields for at least the username and password. If you want to
10# use the user@domain syntax, you might want to have a separate domain
11# field as well.
12#
13# If your users all have the same uig/gid, and have predictable home
14# directories, you can use the static userdb module to generate the home
15# dir based on the username and domain. In this case, you won't need fields
16# for home, uid, or gid in the database.
17#
18# If you prefer to use the sql userdb module, you'll want to add fields
19# for home, uid, and gid. Here is an example table:
20#
21# CREATE TABLE users (
22# username VARCHAR(128) NOT NULL,
23# domain VARCHAR(128) NOT NULL,
24# password VARCHAR(64) NOT NULL,
25# home VARCHAR(255) NOT NULL,
26# uid INTEGER NOT NULL,
27# gid INTEGER NOT NULL,
28# active CHAR(1) DEFAULT 'Y' NOT NULL
29# );
30
31# Database driver: mysql, pgsql, sqlite
32driver = sqlite
33
34# Database connection string. This is driver-specific setting.
35#
36# HA / round-robin load-balancing is supported by giving multiple host
37# settings, like: host=sql1.host.org host=sql2.host.org
38#
39# pgsql:
40# For available options, see the PostgreSQL documention for the
41# PQconnectdb function of libpq.
42# Use maxconns=n (default 5) to change how many connections Dovecot can
43# create to pgsql.
44#
45# mysql:
46# Basic options emulate PostgreSQL option names:
47# host, port, user, password, dbname
48#
49# But also adds some new settings:
50# client_flags - See MySQL manual
51# connect_timeout - Connect timeout in seconds (default: 5)
52# read_timeout - Read timeout in seconds (default: 30)
53# write_timeout - Write timeout in seconds (default: 30)
54# ssl_ca, ssl_ca_path - Set either one or both to enable SSL
55# ssl_cert, ssl_key - For sending client-side certificates to server
56# ssl_cipher - Set minimum allowed cipher security (default: HIGH)
57# ssl_verify_server_cert - Verify that the name in the server SSL certificate
58# matches the host (default: no)
59# option_file - Read options from the given file instead of
60# the default my.cnf location
61# option_group - Read options from the given group (default: client)
62#
63# You can connect to UNIX sockets by using host: host=/var/run/mysql.sock
64# Note that currently you can't use spaces in parameters.
65#
66# sqlite:
67# The path to the database file.
68#
69# Examples:
70# connect = host=192.168.1.1 dbname=users
71# connect = host=sql.example.com dbname=virtual user=virtual password=blarg
72# connect = /etc/dovecot/authdb.sqlite
73#
74connect = /etc/dovecot/authdb.sqlite
75
76# Default password scheme.
77#
78# List of supported schemes is in
79# http://wiki2.dovecot.org/Authentication/PasswordSchemes
80#
81#default_pass_scheme = SHA512-CRYPT
82
83# passdb query to retrieve the password. It can return fields:
84# password - The user's password. This field must be returned.
85# user - user@domain from the database. Needed with case-insensitive lookups.
86# username and domain - An alternative way to represent the "user" field.
87#
88# The "user" field is often necessary with case-insensitive lookups to avoid
89# e.g. "name" and "nAme" logins creating two different mail directories. If
90# your user and domain names are in separate fields, you can return "username"
91# and "domain" fields instead of "user".
92#
93# The query can also return other fields which have a special meaning, see
94# http://wiki2.dovecot.org/PasswordDatabase/ExtraFields
95#
96# Commonly used available substitutions (see http://wiki2.dovecot.org/Variables
97# for full list):
98# %u = entire user@domain
99# %n = user part of user@domain
100# %d = domain part of user@domain
101#
102# Note that these can be used only as input to SQL query. If the query outputs
103# any of these substitutions, they're not touched. Otherwise it would be
104# difficult to have eg. usernames containing '%' characters.
105#
106# Example:
107# password_query = SELECT userid AS user, pw AS password \
108# FROM users WHERE userid = '%u' AND active = 'Y'
109#
110password_query = \
111 SELECT '%u' AS username, domain, password \
112 FROM users WHERE userid = '%n' AND domain = '%d'
113
114# You can update (or modify this a bit to insert) user passwords in a shell with:
115# sqlite3 authdb.sqlite "update users set password='$(doveadm pw -s SHA512-CRYPT -r 1856250)' where userid='USERNAME' and domain = 'DOMAIN';"
116
117
118# userdb query to retrieve the user information. It can return fields:
119# uid - System UID (overrides mail_uid setting)
120# gid - System GID (overrides mail_gid setting)
121# home - Home directory
122# mail - Mail location (overrides mail_location setting)
123#
124# None of these are strictly required. If you use a single UID and GID, and
125# home or mail directory fits to a template string, you could use userdb static
126# instead. For a list of all fields that can be returned, see
127# http://wiki2.dovecot.org/UserDatabase/ExtraFields
128#
129# Examples:
130# user_query = SELECT home, uid, gid FROM users WHERE userid = '%u'
131# user_query = SELECT dir AS home, user AS uid, group AS gid FROM users where userid = '%u'
132# user_query = SELECT home, 501 AS uid, 501 AS gid FROM users WHERE userid = '%u'
133#
134user_query = \
135 SELECT "/var/mail/vhosts/" || '%d' || '/' || '%n' AS home, 145 as uid, 145 as gid
136
137# If you wish to avoid two SQL lookups (passdb + userdb), you can use
138# userdb prefetch instead of userdb sql in dovecot.conf. In that case you'll
139# also have to return userdb fields in password_query prefixed with "userdb_"
140# string. For example:
141password_query = \
142 SELECT '%u' AS user, password, \
143 "/var/mail/vhosts/" || '%d' || '/' || '%n' AS userdb_home, 145 AS userdb_uid, 145 AS userdb_gid \
144 FROM users WHERE userid = '%n' AND domain = '%d'
145
146# Query to get a list of all usernames.
147# This iteration is used for things like globally purging zero refcount emails
148# for all users, but to get all users, we have to iterate the user storage,
149# hence this iterator query is required.
150iterate_query = SELECT userid AS user FROM users
diff --git a/ansible/roles/dovecot/files/dovecot/dovecot.conf b/ansible/roles/dovecot/files/dovecot/dovecot.conf
new file mode 100644
index 0000000..4304fa6
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/dovecot.conf
@@ -0,0 +1,19 @@
1# IMAP for remote access, LMTP for local delivery
2protocols = imap lmtp
3
4# set these to the uid of your `vmail` user
5first_valid_uid = 145
6last_valid_uid = 145
7
8#mail_debug = yes
9##auth_verbose = yes
10##auth_debug = yes
11##auth_debug_passwords = yes
12##auth_verbose_passwords = yes
13
14
15mail_uid = vmail
16mail_gid = vmail
17
18!include conf.d/*.conf
19!include_try local.conf
diff --git a/ansible/roles/dovecot/files/dovecot/sieve-before.d/10-rspamd.sieve b/ansible/roles/dovecot/files/dovecot/sieve-before.d/10-rspamd.sieve
new file mode 100644
index 0000000..7931a71
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/sieve-before.d/10-rspamd.sieve
@@ -0,0 +1,5 @@
1require ["fileinto"];
2
3if header :is "X-Spam" "Yes" {
4 fileinto "Junk";
5}
diff --git a/ansible/roles/dovecot/files/dovecot/sieve/report-ham.sieve b/ansible/roles/dovecot/files/dovecot/sieve/report-ham.sieve
new file mode 100644
index 0000000..2ad40aa
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/sieve/report-ham.sieve
@@ -0,0 +1,23 @@
1require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
2
3if environment :matches "imap.mailbox" "*" {
4 set "mailbox" "${1}";
5}
6
7# This line is important because when we delete from Junk/Spam,
8# messages get moved to Trash, which tirggers the "message moved out of
9# spam" script (this script) which—usually!—trains the originally classified
10# Spam as not-spam.
11# BUT, this is just a delete! If we train our spam as not-spam on delete, that
12# defeats our goals.
13# In short, this always gets run on a message being moved out of Spam, but if
14# the target mailbox is Trash, just don't run the trainer this time.
15if string "${mailbox}" "Trash" {
16 stop;
17}
18
19if environment :matches "imap.email" "*" {
20 set "email" "${1}";
21}
22
23pipe :copy "train-ham.sh" [ "${email}" ];
diff --git a/ansible/roles/dovecot/files/dovecot/sieve/report-spam.sieve b/ansible/roles/dovecot/files/dovecot/sieve/report-spam.sieve
new file mode 100644
index 0000000..4ed95d7
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/sieve/report-spam.sieve
@@ -0,0 +1,7 @@
1require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
2
3if environment :matches "imap.email" "*" {
4 set "email" "${1}";
5}
6
7pipe :copy "train-spam.sh" [ "${email}" ];
diff --git a/ansible/roles/dovecot/files/dovecot/sieve/train-ham.sh b/ansible/roles/dovecot/files/dovecot/sieve/train-ham.sh
new file mode 100755
index 0000000..b0f30fd
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/sieve/train-ham.sh
@@ -0,0 +1 @@
exec /usr/bin/rspamc --connect localhost:11334 learn_ham
diff --git a/ansible/roles/dovecot/files/dovecot/sieve/train-spam.sh b/ansible/roles/dovecot/files/dovecot/sieve/train-spam.sh
new file mode 100755
index 0000000..bf1b920
--- /dev/null
+++ b/ansible/roles/dovecot/files/dovecot/sieve/train-spam.sh
@@ -0,0 +1 @@
exec /usr/bin/rspamc --connect localhost:11334 learn_spam
diff --git a/ansible/roles/dovecot/handlers/main.yml b/ansible/roles/dovecot/handlers/main.yml
new file mode 100644
index 0000000..dda7930
--- /dev/null
+++ b/ansible/roles/dovecot/handlers/main.yml
@@ -0,0 +1,31 @@
1---
2- name: restart dovecot
3 service:
4 name: dovecot
5 state: restarted
6
7- name: reload dovecot
8 service:
9 name: dovecot
10 state: reloaded
11
12# We intentionally don't have a "creates:" guard on the resieve handlers
13# because if they get called we need to re-run them on any changes of
14# the underlying script itself regardless whether the result .svbin
15# already exists or not.
16- name: resieve spam
17 command: sievec report-spam.sieve
18 args:
19 chdir: /etc/dovecot/sieve
20
21- name: resieve ham
22 command: sievec report-ham.sieve
23 args:
24 chdir: /etc/dovecot/sieve
25
26- name: resieve spam mover
27 command: sievec 10-rspamd.sieve
28 args:
29 chdir: /etc/dovecot/sieve-before.d
30 creates: 10-rspamd.svbin
31
diff --git a/ansible/roles/dovecot/tasks/main.yml b/ansible/roles/dovecot/tasks/main.yml
new file mode 100644
index 0000000..6e097c1
--- /dev/null
+++ b/ansible/roles/dovecot/tasks/main.yml
@@ -0,0 +1,110 @@
1---
2# dovecot install and configuration
3- name: install dovecot
4 apt:
5 state: latest
6 pkg:
7 - dovecot-imapd
8 - dovecot-lmtpd
9 - dovecot-sieve
10 - dovecot-sqlite
11
12# Convert existing maildir to mdbox (local on-fs dirs) with:
13# dsync -o mail_location=mdbox:herebox mirror maildir:Maildir
14# Or, you can pull from a remote site:
15# Below, -R means REVERSE backup so PULL messages FROM vorash INTO mdbox,
16# otherwise, it's a PUSH backup and mdbox PUSHES to vorash which isn't what we want
17# doveadm -o mail_location=mdbox:herebox backup -R ssh -J [email protected] matt@vorash doveadm dsync-server
18- name: create mail spool dirs
19 file:
20 path: /var/mail/local
21 owner: root
22 group: mail
23 mode: 0775
24 state: directory
25
26- name: create dovecot virtual mailbox group
27 group:
28 name: vmail
29 gid: 145
30 state: present
31
32- name: create dovecot virtual mailbox and virtual authentication account
33 user:
34 name: vmail
35 uid: 145
36 group: vmail
37 shell: /sbin/nologin
38 create_home: yes
39 home: /var/mail/vhosts
40 state: present
41
42- name: give dovecot user permission to read private keys
43 user:
44 name: dovecot
45 groups: ssl-cert
46 append: yes
47
48# Create new passwords with:
49# time doveadm pw -s SHA512-CRYPT -r 1856250
50- name: copy dovecot configs and userdb
51 copy:
52 src: dovecot/
53 dest: /etc/dovecot/
54 mode: preserve
55 notify:
56 - resieve spam
57 - resieve ham
58 - resieve spam mover
59 - restart dovecot
60
61# This permission is important because dovecot has multiple users:
62# - dovecot
63# - dovenull
64# - vmail
65# but login processes are run by the 'vmail' user, so 'vmail' must have read
66# access to the DB
67- name: fix user permissions on authdb
68 file:
69 path: /etc/dovecot/authdb.sqlite
70 owner: vmail
71 group: vmail
72 mode: 0600
73
74- name: instantiate dovecot SSL template with host vars
75 template:
76 src: dovecot/conf.d/10-ssl.conf.j2
77 dest: /etc/dovecot/conf.d/10-ssl.conf
78 notify:
79 - restart dovecot # NB this could be a reload instead
80
81# Dovecot mdbox format requires a purge to remove storage space
82# allocated to messages that have been fully deleted by users.
83# (it's an append-only refcounting system, so when a refcount becomes
84# zero on final delete, it needs some cleanup to rewrite the old
85# pack files without the deleted emails present anymore.)
86- cron:
87 name: setup cron so dovecot can GC mailboxes
88 minute: 0
89 hour: 3
90 user: vmail
91 job: "doveadm purge -A"
92 cron_file: dovecot_maint_purge
93
94
95# verify everything is running
96- name: verify services are running in dependency order
97 service:
98 name: "{{ item }}"
99 enabled: yes
100 state: started
101 loop:
102 - dovecot
103
104- name: reload if certs newish
105 include_role:
106 name: certreload
107 vars:
108 certreload:
109 notifiers:
110 - reload dovecot
diff --git a/ansible/roles/dovecot/templates/dovecot/conf.d/10-ssl.conf.j2 b/ansible/roles/dovecot/templates/dovecot/conf.d/10-ssl.conf.j2
new file mode 100644
index 0000000..c1654cd
--- /dev/null
+++ b/ansible/roles/dovecot/templates/dovecot/conf.d/10-ssl.conf.j2
@@ -0,0 +1,22 @@
1# require SSL for all non-localhost connections
2ssl = required
3
4# Config detials at https://wiki.dovecot.org/SSL/DovecotConfiguration
5ssl_cert = </etc/ssl/{{ network.hostname.public }}-cert-combined.rsa2048.pem
6ssl_key = </etc/ssl/private/{{ network.hostname.public }}-key.rsa2048.pem
7
8# Since v2.2.31+ you can specify alternative ssl certificate
9# if the algorithm differs from the primary certificate.
10# This is useful when migrating to e.g. ECDSA certificate.
11ssl_alt_cert = </etc/ssl/{{ network.hostname.public }}-cert-combined.prime256v1.pem
12ssl_alt_key = </etc/ssl/private/{{ network.hostname.public }}-key.prime256v1.pem
13
14# require modern crypto - taken from Mozilla's SSL recommendations page
15ssl_dh_parameters_length = 4096
16ssl_protocols = !SSLv3 !TLSv1 !TLSv1.1 TLSv1.2
17ssl_cipher_list = ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
18ssl_prefer_server_ciphers = yes
19
20# newer dovecot 2.3+
21#ssl_min_protocol = TLSv1.2
22#ssl_dh = /etc/ssl/ffdhe4096.pem
Powered by cgit v1.2.3 (git 2.41.0)