# # !!! This file is managed by Ansible !!! # ## maddy 0.4 - default configuration file log syslog /var/log/maddy.log # ---------------------------------------------------------------------------- # Base variables $(hostname) = {{services.maddy.hostname}} $(primary_domain) = ctu.cx $(local_domains) = $(hostname) $(primary_domain) antifa.jetzt thein.ovh ctucx.de trans-agenda.de tls file {{services.maddy.ssl_cert}} {{services.maddy.ssl_privkey}} # ---------------------------------------------------------------------------- # Local storage & authentication # pass_table provides local hashed passwords storage for authentication of # users. It can be configured to use any "table" module, in default # configuration a table in SQLite DB is used. # Table can be replaced to use e.g. a file for passwords. Or pass_table module # can be replaced altogether to use some external source of credentials (e.g. # PAM, /etc/shadow file). # # If table module supports it (sql_table does) - credentials can be managed # using 'maddyctl creds' command. auth.pass_table local_authdb { table sql_table { driver sqlite3 dsn credentials.db table_name passwords } } # imapsql module stores all indexes and metadata necessary for IMAP using a # relational database. It is used by IMAP endpoint for mailbox access and # also by SMTP & Submission endpoints for delivery of local messages. # # IMAP accounts, mailboxes and all message metadata can be inspected using # imap-* subcommands of maddyctl utility. storage.imapsql local_mailboxes { driver sqlite3 dsn imapsql.db } # ---------------------------------------------------------------------------- # SMTP endpoints + message routing hostname $(hostname) msgpipeline local_routing { dmarc yes check { require_mx_record dkim spf } # Insert handling for special-purpose local domains here. # e.g. # destination lists.example.org { # deliver_to lmtp tcp://127.0.0.1:8024 # } destination postmaster $(local_domains) { modify { replace_rcpt static { entry postmaster postmaster@$(primary_domain) entry leon@thein.ovh leah@ctu.cx entry leah@thein.ovh leah@ctu.cx entry leah@antifa.jetzt leah@ctu.cx } # Implement plus-address notation. replace_rcpt regexp "(.+)\+(.+)@(.+)" "$1@$3" replace_rcpt regexp "(.+)@ctucx.de" "leah@ctu.cx" replace_rcpt regexp "(.+)@ctu.cx" "leah@ctu.cx" } deliver_to &local_mailboxes } default_destination { reject 550 5.1.1 "User doesn't exist" } } smtp tcp://0.0.0.0:25 { limits { # Up to 20 msgs/sec across max. 10 SMTP connections. all rate 20 1s all concurrency 10 } source $(local_domains) { reject 501 5.1.8 "Use Submission for outgoing SMTP" } default_source { destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { reject 550 5.1.1 "User doesn't exist" } } } submission tls://0.0.0.0:465 tcp://0.0.0.0:587 { limits { # Up to 50 msgs/sec across any amount of SMTP connections. all rate 50 1s } auth &local_authdb source $(local_domains) { destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { modify { dkim $(primary_domain) $(local_domains) default { newkey_algo ed25519 } } deliver_to &remote_queue } } default_source { reject 501 5.1.8 "Non-local sender domain" } } target.remote outbound_delivery { limits { # Up to 20 msgs/sec across max. 10 SMTP connections # for each recipient domain. destination rate 20 1s destination concurrency 10 } mx_auth { dane mtasts { cache fs fs_dir mtasts_cache/ } local_policy { min_tls_level encrypted min_mx_level none } } } target.queue remote_queue { target &outbound_delivery max_parallelism 16 max_tries 4 autogenerated_msg_domain $(primary_domain) bounce { destination postmaster $(local_domains) { deliver_to &local_routing } default_destination { reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" } } } # ---------------------------------------------------------------------------- # IMAP endpoints imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { auth &local_authdb storage &local_mailboxes }