From f7fb8121fd8e8942a56b97c4f5cc1b704c0608ab Mon Sep 17 00:00:00 2001 From: "Lennart J. Kurzweg (Nx2)" Date: Mon, 4 May 2026 13:45:11 +0200 Subject: [PATCH] maddy conf --- system-modules/nx2site/maddy.nix | 171 +++++++++++++++++++++++++++---- 1 file changed, 151 insertions(+), 20 deletions(-) diff --git a/system-modules/nx2site/maddy.nix b/system-modules/nx2site/maddy.nix index 91a5c92..f734de8 100644 --- a/system-modules/nx2site/maddy.nix +++ b/system-modules/nx2site/maddy.nix @@ -1,4 +1,6 @@ -{ config, pkgs, ... }@all: with all; { +{ config, pkgs, ... }@all: with all; let + users = [ "nxcaldav" "nextcloud" "lennart" "daniel" "diane" "georg" "tessa" ]; +in { sops.secrets = { "nx2site/maddy/nxcaldav_password" = { owner = "maddy"; group = "maddy"; mode = "600"; }; "nx2site/maddy/nextcloud_password" = { owner = "maddy"; group = "maddy"; mode = "600"; }; @@ -16,7 +18,7 @@ primaryDomain = hyper.domain; user = "maddy"; group = "maddy"; - hostname = "mail.${hyper.domain}"; + hostname = "ssh.${hyper.domain}"; ensureAccounts = [ "nxcaldav@${hyper.domain}" "nextcloud@${hyper.domain}" @@ -46,42 +48,171 @@ }; # Enable TLS listeners. Configuring this via the module is not yet # implemented, see https://github.com/NixOS/nixpkgs/pull/153372 - config = (builtins.replaceStrings [ - "imap tcp://0.0.0.0:143" - "submission tcp://0.0.0.0:587" - ] [ - "imap tls://0.0.0.0:993 tcp://0.0.0.0:143" - "submission tls://0.0.0.0:465 tcp://0.0.0.0:587" - ] options.services.maddy.config.default) + '' - smtp tcp://127.0.0.1:2525 { - tls off - # 1. Allow local delivery (e.g., app sending to admin@nx2.site) - destination postmaster $(local_domains) { + config = let + admin = "lennart@${hyper.domain}"; + domains = hyper.domain; # could be more + inherit (hyper) domain; + # nix adds 3 variables, hostname, and tls info before the file (see /etc/maddy/maddy.conf) + in /* ini */'' + auth.pass_table local_authdb { + table sql_table { + driver sqlite3 + dsn credentials.db + table_name passwords + } + } + + storage.imapsql local_mailboxes { + driver sqlite3 + dsn imapsql.db + } + + table.chain local_rewrites { + # tagging with - or + + # alice-something@${domain} or alice+something@${domain} lands in inbox alice@${domain} + optional_step regexp "(.+)[\+-](.+)@(.+)" "$1@$3" + optional_step static { + entry postmaster ${admin} + entry admin ${admin} + } + } + + msgpipeline local_routing { + destination ${domains} { + modify { + replace_rcpt &local_rewrites + } + reroute { + destination_in &local_mailboxes { + deliver_to &local_mailboxes + } + default_destination { + modify { + replace_rcpt regexp ".*" "${admin}" + } + deliver_to &local_mailboxes + } + } + } + # should never happen + default_destination { + reject 550 5.1.1 "User doesn't exist" + } + } + + smtp tcp://0.0.0.0:25 { + limits { + all rate 20 1s + all concurrency 10 + } + dmarc yes + check { + require_mx_record + dkim + spf + } + source ${domains} { + reject 501 5.1.8 "Use Submission for outgoing SMTP" + } + default_source { + destination postmaster ${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 { + all rate 50 1s + } + auth &local_authdb + source ${domains} { + check { + authorize_sender { + prepare_email &local_rewrites + user_to_email identity + } + } + destination postmaster ${domains} { deliver_to &local_routing } - # 2. Allow remote delivery (e.g., app sending to gmail.com) default_destination { modify { - # Ensure outgoing mail is signed even if sent via 2525 - dkim $(primary_domain) $(local_domains) default + dkim ${domain} ${domains} default + } + deliver_to &remote_queue + } + } + default_source { + reject 501 5.1.8 "Non-local sender domain" + } + } + + target.remote outbound_delivery { + limits { + 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 + autogenerated_msg_domain ${domain} + bounce { + destination postmaster ${domains} { + deliver_to &local_routing + } + default_destination { + reject 550 5.0.0 "Refusing to send DSNs to non-local addresses" + } + } + } + + imap tls://0.0.0.0:993 tcp://0.0.0.0:143 { + auth &local_authdb + storage &local_mailboxes + } + + # localhost only - test purposes only (->spam!) + smtp tcp://127.0.0.1:2525 { + tls off + destination postmaster ${domains} { + deliver_to &local_routing + } + default_destination { + modify { + dkim ${domain} ${domains} default } deliver_to &remote_queue } } # nx2s-email-relay backdor smtp tcp://0.0.0.0:25025 { - # tls off - + # 1. Allow incoming mail from the VM for your domains - destination postmaster $(local_domains) { + destination postmaster ${domains} { deliver_to &local_routing } - # 2. Prevent the world from using you as an open relay default_destination { reject 521 5.0.0 "User not local" } } + ''; }; }