Compare commits

...

5 commits

10 changed files with 157 additions and 103 deletions

View file

@ -1,17 +0,0 @@
connect = host=${host} dbname=${name} user=${user} password=${password}
driver = pgsql
default_pass_scheme = ARGON2ID
user_query = SELECT '/var/vmail/%u' AS home, 'vmail' AS uid, 'vmail' AS gid
iterate_query = SELECT CONCAT(users.name, '@', domains.name) AS user \
FROM users \
LEFT JOIN domains ON users.domain_id = domains.id \
WHERE redirect IS NULL
password_query = SELECT CONCAT(users.name, '@', domains.name) AS user, password \
FROM users \
LEFT JOIN domains ON users.domain_id = domains.id \
WHERE redirect IS NULL \
AND users.name = SPLIT_PART('%u', '@', 1) \
AND domains.name = SPLIT_PART('%u', '@', 2)

View file

@ -1,13 +1,17 @@
dovecot_config_version = ${config_version}
dovecot_storage_version = ${storage_version}
protocols = imap lmtp sieve protocols = imap lmtp sieve
auth_mechanisms = plain login auth_mechanisms = plain login
mail_privileged_group = mail
ssl = required ssl = required
ssl_cert = </var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/fullchain.pem ssl_server_cert_file = /var/lib/dehydrated/certs/${hostname}/fullchain.pem
ssl_key = </var/lib/dehydrated/certs/${node.metadata.get('mailserver/hostname')}/privkey.pem ssl_server_key_file = /var/lib/dehydrated/certs/${hostname}/privkey.pem
ssl_dh = </etc/dovecot/dhparam.pem ssl_server_dh_file = /etc/dovecot/dhparam.pem
ssl_client_ca_dir = /etc/ssl/certs ssl_client_ca_dir = /etc/ssl/certs
mail_location = maildir:${node.metadata.get('mailserver/maildir')}/%u:INDEX=${node.metadata.get('mailserver/maildir')}/index/%u mail_driver = maildir
mail_plugins = fts fts_xapian mail_path = ${maildir}/%{user}
mail_index_path = ${maildir}/index/%{user}
mail_plugins = fts fts_flatcurve
namespace inbox { namespace inbox {
inbox = yes inbox = yes
@ -30,14 +34,46 @@ namespace inbox {
} }
} }
passdb { # postgres passdb userdb
driver = sql
args = /etc/dovecot/dovecot-sql.conf sql_driver = pgsql
pgsql main {
parameters {
host = ${db_host}
dbname = ${db_name}
user = ${db_user}
password = ${db_password}
}
} }
# use sql for userdb too, to enable iterate_query
userdb { passdb sql {
driver = sql passdb_default_password_scheme = ARGON2ID
args = /etc/dovecot/dovecot-sql.conf
query = SELECT \
CONCAT(users.name, '@', domains.name) AS "user", \
password \
FROM users \
LEFT JOIN domains ON users.domain_id = domains.id \
WHERE redirect IS NULL \
AND users.name = SPLIT_PART('%{user}', '@', 1) \
AND domains.name = SPLIT_PART('%{user}', '@', 2)
}
mail_uid = vmail
mail_gid = vmail
userdb sql {
query = SELECT \
'/var/vmail/%{user}' AS home, \
'vmail' AS uid, \
'vmail' AS gid
iterate_query = SELECT \
CONCAT(users.name, '@', domains.name) AS username \
FROM users \
LEFT JOIN domains ON users.domain_id = domains.id \
WHERE redirect IS NULL
} }
service auth { service auth {
@ -67,10 +103,9 @@ service stats {
} }
} }
service managesieve-login { service managesieve-login {
inet_listener sieve { #inet_listener sieve {}
} process_min_avail = 1
process_min_avail = 0 process_limit = 1
service_count = 1
vsz_limit = 64 M vsz_limit = 64 M
} }
service managesieve { service managesieve {
@ -78,31 +113,53 @@ service managesieve {
} }
protocol imap { protocol imap {
mail_plugins = $mail_plugins imap_sieve mail_plugins = fts fts_flatcurve imap_sieve
mail_max_userip_connections = 50 mail_max_userip_connections = 50
imap_idle_notify_interval = 29 mins imap_idle_notify_interval = 29 mins
} }
protocol lmtp { protocol lmtp {
mail_plugins = $mail_plugins sieve mail_plugins = fts fts_flatcurve sieve
} }
protocol sieve {
plugin { # Persönliches Skript (deine alte Datei /var/vmail/sieve/%u.sieve)
sieve = /var/vmail/sieve/%u.sieve sieve_script personal {
sieve_storage = /var/vmail/sieve/%u/ driver = file
} # Verzeichnis mit (evtl. mehreren) Sieve-Skripten des Users
path = /var/vmail/sieve/%{user}/
# Aktives Skript (entspricht früher "sieve = /var/vmail/sieve/%u.sieve")
active_path = /var/vmail/sieve/%{user}.sieve
}
# Globales After-Skript (dein früheres "sieve_after = …")
sieve_script after {
type = after
driver = file
path = /var/vmail/sieve/global/spam-to-folder.sieve
} }
# fulltext search # fulltext search
plugin { language en {
fts = xapian
fts_xapian = partial=3 full=20 verbose=0
fts_autoindex = yes
fts_enforced = yes
# Index attachements
fts_decoder = decode2text
} }
language de {
default = yes
}
language_tokenizers = generic email-address
fts flatcurve {
substring_search = yes
# rotate_count = 5000 # DB-Rotation nach X Mails
# rotate_time = 5s # oder zeitbasiert rotieren
# optimize_limit = 10
# min_term_size = 3
}
fts_autoindex = yes
fts_decoder_driver = script
fts_decoder_script_socket_path = decode2text
service indexer-worker { service indexer-worker {
vsz_limit = ${indexer_ram} process_limit = ${indexer_cores}
vsz_limit = ${indexer_ram}M
} }
service decode2text { service decode2text {
executable = script /usr/local/libexec/dovecot/decode2text.sh executable = script /usr/local/libexec/dovecot/decode2text.sh
@ -112,24 +169,39 @@ service decode2text {
} }
} }
# spam filter mailbox Junk {
plugin { sieve_script learn_spam {
sieve_plugins = sieve_imapsieve sieve_extprograms driver = file
sieve_dir = /var/vmail/sieve/%u/ type = before
sieve = /var/vmail/sieve/%u.sieve cause = copy
sieve_pipe_bin_dir = /var/vmail/sieve/bin path = /var/vmail/sieve/global/learn-spam.sieve
sieve_extensions = +vnd.dovecot.pipe }
sieve_after = /var/vmail/sieve/global/spam-to-folder.sieve
# From elsewhere to Spam folder
imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY
imapsieve_mailbox1_before = file:/var/vmail/sieve/global/learn-spam.sieve
# From Spam folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Junk
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/var/vmail/sieve/global/learn-ham.sieve
} }
imapsieve_from Junk {
sieve_script learn_ham {
driver = file
type = before
cause = copy
path = /var/vmail/sieve/global/learn-ham.sieve
}
}
# Extprograms-Plugin einschalten
sieve_plugins {
sieve_extprograms = yes
}
# Welche Sieve-Erweiterungen dürfen genutzt werden?
# Empfehlung: nur global erlauben (nicht in User-Skripten):
sieve_global_extensions {
vnd.dovecot.pipe = yes
# vnd.dovecot.filter = yes # nur falls gebraucht
# vnd.dovecot.execute = yes # nur falls gebraucht
}
# Verzeichnis mit deinen Skripten/Binaries für :pipe
sieve_pipe_bin_dir = /var/vmail/sieve/bin
# (optional, analog für :filter / :execute)
# sieve_filter_bin_dir = /var/vmail/sieve/filter
# sieve_execute_bin_dir = /var/vmail/sieve/execute

View file

@ -44,6 +44,16 @@ files = {
'context': { 'context': {
'admin_email': node.metadata.get('mailserver/admin_email'), 'admin_email': node.metadata.get('mailserver/admin_email'),
'indexer_ram': node.metadata.get('dovecot/indexer_ram'), 'indexer_ram': node.metadata.get('dovecot/indexer_ram'),
'config_version': node.metadata.get('dovecot/config_version'),
'storage_version': node.metadata.get('dovecot/storage_version'),
'maildir': node.metadata.get('mailserver/maildir'),
'hostname': node.metadata.get('mailserver/hostname'),
'db_host': node.metadata.get('mailserver/database/host'),
'db_name': node.metadata.get('mailserver/database/name'),
'db_user': node.metadata.get('mailserver/database/user'),
'db_password': node.metadata.get('mailserver/database/password'),
'indexer_cores': node.metadata.get('vm/cores'),
'indexer_ram': node.metadata.get('vm/ram')//2,
}, },
'needs': { 'needs': {
'pkg_apt:' 'pkg_apt:'
@ -52,29 +62,9 @@ files = {
'svc_systemd:dovecot:restart', 'svc_systemd:dovecot:restart',
}, },
}, },
'/etc/dovecot/dovecot-sql.conf': {
'content_type': 'mako',
'context': node.metadata.get('mailserver/database'),
'needs': {
'pkg_apt:'
},
'triggers': {
'svc_systemd:dovecot:restart',
},
},
'/etc/dovecot/dhparam.pem': { '/etc/dovecot/dhparam.pem': {
'content_type': 'any', 'content_type': 'any',
}, },
'/etc/dovecot/dovecot-sql.conf': {
'content_type': 'mako',
'context': node.metadata.get('mailserver/database'),
'needs': {
'pkg_apt:'
},
'triggers': {
'svc_systemd:dovecot:restart',
},
},
'/var/vmail/sieve/global/spam-to-folder.sieve': { '/var/vmail/sieve/global/spam-to-folder.sieve': {
'owner': 'vmail', 'owner': 'vmail',
'group': 'vmail', 'group': 'vmail',
@ -131,7 +121,6 @@ svc_systemd = {
'action:letsencrypt_update_certificates', 'action:letsencrypt_update_certificates',
'action:dovecot_generate_dhparam', 'action:dovecot_generate_dhparam',
'file:/etc/dovecot/dovecot.conf', 'file:/etc/dovecot/dovecot.conf',
'file:/etc/dovecot/dovecot-sql.conf',
}, },
}, },
} }

View file

@ -8,7 +8,7 @@ defaults = {
'dovecot-sieve': {}, 'dovecot-sieve': {},
'dovecot-managesieved': {}, 'dovecot-managesieved': {},
# fulltext search # fulltext search
'dovecot-fts-xapian': {}, # buster-backports 'dovecot-flatcurve': {}, # buster-backports
'poppler-utils': {}, # pdftotext 'poppler-utils': {}, # pdftotext
'catdoc': {}, # catdoc, catppt, xls2csv 'catdoc': {}, # catdoc, catppt, xls2csv
}, },

View file

@ -32,10 +32,14 @@ defaults = {
'tank/vmail': { 'tank/vmail': {
'mountpoint': '/var/vmail', 'mountpoint': '/var/vmail',
'compression': 'on', 'compression': 'on',
'atime': 'off',
'recordsize': '16384',
}, },
'tank/vmail/index': { 'tank/vmail/index': {
'mountpoint': '/var/vmail/index', 'mountpoint': '/var/vmail/index',
'compression': 'on', 'compression': 'on',
'atime': 'off',
'recordsize': '4096',
'com.sun:auto-snapshot': 'false', 'com.sun:auto-snapshot': 'false',
'backup': False, 'backup': False,
}, },

View file

@ -9,6 +9,7 @@ directories = {
}, },
'/var/lib/redis': { '/var/lib/redis': {
'owner': 'redis', 'owner': 'redis',
'group': 'redis',
'mode': '0750', 'mode': '0750',
'needs': [ 'needs': [
'pkg_apt:redis-server', 'pkg_apt:redis-server',

View file

@ -7,18 +7,16 @@ $config['enable_installer'] = true;
/* Local configuration for Roundcube Webmail */ /* Local configuration for Roundcube Webmail */
$config['db_dsnw'] = '${database['provider']}://${database['user']}:${database['password']}@${database['host']}/${database['name']}'; $config['db_dsnw'] = '${database['provider']}://${database['user']}:${database['password']}@${database['host']}/${database['name']}';
$config['imap_host'] = 'localhost'; $config['imap_host'] = 'ssl://${imap_host}';
$config['imap_port'] = 993;
$config['smtp_host'] = 'tls://localhost'; $config['smtp_host'] = 'tls://localhost';
$config['smtp_port'] = 587;
$config['smtp_user'] = '%u'; $config['smtp_user'] = '%u';
$config['smtp_pass'] = '%p'; $config['smtp_pass'] = '%p';
#$config['imap_debug'] = true;
#$config['smtp_debug'] = true;
$config['support_url'] = ''; $config['support_url'] = '';
$config['des_key'] = '${des_key}'; $config['des_key'] = '${des_key}';
$config['product_name'] = '${product_name}'; $config['product_name'] = '${product_name}';
$config['plugins'] = array(${', '.join(f'"{plugin}"' for plugin in plugins)}); $config['plugins'] = array(${', '.join(f'"{plugin}"' for plugin in plugins)});
$config['language'] = 'de_DE'; $config['language'] = 'de_DE';
$config['smtp_conn_options'] = array(
'ssl' => array(
'verify_peer' => false,
'verify_peer_name' => false,
),
);

View file

@ -61,6 +61,7 @@ files['/opt/roundcube/config/config.inc.php'] = {
'des_key': node.metadata.get('roundcube/des_key'), 'des_key': node.metadata.get('roundcube/des_key'),
'database': node.metadata.get('roundcube/database'), 'database': node.metadata.get('roundcube/database'),
'plugins': node.metadata.get('roundcube/plugins'), 'plugins': node.metadata.get('roundcube/plugins'),
'imap_host': node.metadata.get('mailserver/hostname'),
}, },
'needs': [ 'needs': [
'action:chown_roundcube', 'action:chown_roundcube',

View file

@ -1,5 +1,5 @@
defaults = { defaults = {
'systemd-swap': 2*10**9, 'systemd-swap': 2*(2**30), # 2GiB
'systemd': { 'systemd': {
'units': { 'units': {
'swapfile.swap': { 'swapfile.swap': {

View file

@ -2,7 +2,7 @@
'hostname': '49.12.184.229', 'hostname': '49.12.184.229',
'groups': [ 'groups': [
'backup', 'backup',
'debian-12', 'debian-13',
'hetzner-cloud', 'hetzner-cloud',
'mailserver', 'mailserver',
'monitored', 'monitored',
@ -18,6 +18,7 @@
#'nginx-rtmps', #'nginx-rtmps',
'wireguard', 'wireguard',
'zfs', 'zfs',
'systemd-swap',
], ],
'metadata': { 'metadata': {
'id': 'ea29bdf0-0b47-4bf4-8346-67d60c9dc4ae', 'id': 'ea29bdf0-0b47-4bf4-8346-67d60c9dc4ae',
@ -34,6 +35,7 @@
'gateway6': 'fe80::1', 'gateway6': 'fe80::1',
} }
}, },
'systemd-swap': 4*2**30, # clamav alleine braucht 1,3G
'bind': { 'bind': {
'hostname': 'resolver.name', 'hostname': 'resolver.name',
'acme_zone': 'acme.sublimity.de', 'acme_zone': 'acme.sublimity.de',
@ -108,6 +110,10 @@
'elimu-kwanza.de', 'elimu-kwanza.de',
}, },
}, },
'dovecot': {
'config_version': '2.4.1',
'storage_version': '2.4.1',
},
'rspamd': { 'rspamd': {
'hostname': 'rspamd.sublimity.de', 'hostname': 'rspamd.sublimity.de',
}, },
@ -162,7 +168,7 @@
}, },
'roundcube': { 'roundcube': {
'product_name': 'Sublimity Mail', 'product_name': 'Sublimity Mail',
'version': '1.6.7', 'version': '1.6.11',
'installer': False, 'installer': False,
}, },
'vm': { 'vm': {