Maddy: Difference between revisions
imported>Onny mNo edit summary |
m Add alternate way of generating TLSA |
||
(31 intermediate revisions by 3 users not shown) | |||
Line 3: | Line 3: | ||
== Installation == | == Installation == | ||
The following example enables the Maddy mail server on localhost, listening on mail delivery SMTP/Submission ports (<code>25, 587</code>) and IMAP port (<code>143</code>) for mail clients to connect to. Mailboxes for the accounts <code>postmaster@example.org</code> and <code>user1@example.org</code> get created if they don't exist yet. | |||
The following example enables the Maddy mail server listening on mail delivery SMTP/Submission ports (<code>25, 587</code>) and IMAP | |||
Mailboxes for the accounts <code>postmaster@example.org</code> and <code>user1@example.org</code> get created if they don't exist yet. | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
services.maddy = { | services.maddy = { | ||
enable = true; | enable = true; | ||
primaryDomain = "localhost"; | |||
primaryDomain = " | |||
ensureAccounts = [ | ensureAccounts = [ | ||
"user1@example.org" | "user1@example.org" | ||
"postmaster@example.org" | "postmaster@example.org" | ||
]; | ]; | ||
ensureCredentials = { | |||
# Do not use this in production. This will make passwords world-readable | |||
# in the Nix store | |||
"user1@example.org".passwordFile = "${pkgs.writeText "postmaster" "test"}"; | |||
"postmaster@example.org".passwordFile = "${pkgs.writeText "postmaster" "test"}"; | |||
}; | |||
}; | }; | ||
</nowiki>}} | </nowiki>}} | ||
TLS certificates | This local test setup doesn't provide secure TLS connections and should be used only for testing purpose. | ||
== Configuration == | |||
=== TLS === | |||
The following example changes the hostname for the mail server to the public domain <code>example.org</code>. TLS certificates are obtained using using the ACME dns-01 challenge. This requires API access to your domain provider. See [https://maddy.email/reference/tls-acme/ upstream documentation] for a list on supported providers and how to configure them. | |||
Further the TLS connection is enabled on IMAP port <code>993</code> and Submission port <code>465</code>. | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
services.maddy = { | |||
[ | enable = true; | ||
openFirewall = true; | |||
primaryDomain = "example.org"; | |||
tls = { | |||
loader = "acme"; | |||
extraConfig = '' | |||
email put-your-email-here@example.org | |||
agreed # indicate your agreement with Let's Encrypt ToS | |||
host ${config.services.maddy.primaryDomain} | |||
challenge dns-01 | |||
dns gandi { | |||
api_token "{env:GANDI_API_KEY}" | |||
} | |||
''; | |||
}; | |||
# 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; | |||
# Reading secrets from a file. Do not use this example in production | |||
# since it stores the keys world-readable in the Nix store. | |||
secrets = [ "${pkgs.writeText "secrets" '' | |||
GANDI_API_KEY=1234 | |||
''}" ]; | |||
}; | |||
# Opening ports for additional TLS listeners. This is not yet | |||
# implemented in the module. | |||
networking.firewall.allowedTCPPorts = [ 993 465 ]; | |||
</nowiki>}} | </nowiki>}} | ||
== | Alternativley certificates can be manually loaded with setting <code>tls.loader = "file";</code> and manually specifiying key and certificates file paths using the <code>tls.certificates = [];</code> option. In this case, more ACME protocols and providers are available when using the native NixOS [[ACME]] module or manual client tools like [[Certbot]]. | ||
=== DNS records === | === DNS records === | ||
Line 94: | Line 122: | ||
Replace the IP <code>1.2.3.4</code> with the IP of your mail server. | Replace the IP <code>1.2.3.4</code> with the IP of your mail server. | ||
=== MTA-STS | === MTA-STS === | ||
MTA-STS enforces secure TLS configuration for servers which support this standard. We already advertised this feature in the DNS records above, but we also have to serve a static configuration file using a web server. We use the web server [[Caddy]] to do this but of course you can | MTA-STS enforces secure TLS configuration for servers which support this standard. We already advertised this feature in the DNS records above, but we also have to serve a static configuration file using a web server. We use the web server [[Caddy]] to do this but of course you can other Web Servers too. | ||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
Line 121: | Line 149: | ||
Replace the domain <code>mta-sts.example.org</code> and the domain <code>mx1.example.org</code> with the ones you're using. | Replace the domain <code>mta-sts.example.org</code> and the domain <code>mx1.example.org</code> with the ones you're using. | ||
Using a TLSA (DANE) record is recommended to bind TLS-certificates to a server. You can generate the key using following command | === TLSA (DANE) === | ||
Using a TLSA (DANE) record is recommended to bind TLS-certificates to a server. Your nameserver needs DNSSEC support for it. You can generate the key using following command | |||
<syntaxhighlight lang="console"> | <syntaxhighlight lang="console"> | ||
# nix shell nixpkgs#hash-slinger --command tlsa --create --selector 1 --protocol tcp -p 25 --create mx1.example.org | # nix shell nixpkgs#hash-slinger --command tlsa --create --selector 1 --protocol tcp -p 25 --create mx1.example.org | ||
</syntaxhighlight> | </syntaxhighlight> | ||
Or you can generate it directly from the TLS-certificate that you are using with maddy:<syntaxhighlight lang="console"> | |||
# openssl x509 -in cert.pem -pubkey -noout | openssl ec -pubin -outform der | sha256sum | |||
</syntaxhighlight>Add the key to a new TLSA record in your nameserver | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
Line 135: | Line 168: | ||
</nowiki>}} | </nowiki>}} | ||
=== | To verify if the record is set correctly | ||
<syntaxhighlight lang="console"> | |||
# nix shell nixpkgs#dnsutils --command dig _25._tcp.mx1.example.org TLSA +short | |||
3 1 1 7f59d873a70e224b184c95a4eb54caa9621e47d48b4a25d312d83d96 e3498238 | |||
</syntaxhighlight> | |||
Check if DNSSEC is working correctly for your new TLSA record | |||
<syntaxhighlight lang="console"> | |||
# nix shell nixpkgs#dnsutils --command delv _25._tcp.mx1.example.org TLSA @1.1.1.1 | |||
; fully validated | |||
_25._tcp.mx1.example.org. 10800 IN TLSA 3 1 1 7f59d873a70e224b184c95a4eb54caa9621e47d48b4a25d312d83d96 e3498238 | |||
_25._tcp.mx1.example.org. 10800 IN RRSIG TLSA 13 5 10800 20230601000000 20230511000000 39688 example.org. He9VYZ35xTC3fNo8GJa6swPrZodSnjjIWPG6Th2YbsOEKTV1E8eGtJ2A +eyBd9jgG+B3cA/jw8EJHmpvy/buCw== | |||
</syntaxhighlight> | |||
To verify that the TLSA record matches the TLS certificate of the mail server, issue following openssl command | |||
<syntaxhighlight lang="console"> | |||
# openssl s_client -connect mx1.example.org:25 -starttls smtp -dane_tlsa_domain mx1.example.org -dane_tlsa_rrdata "3 1 1 7f59d873a70e224b184c95a4eb54caa9621e47d48b4a25d312d83d96" | |||
[...] | |||
Verify return code: 0 (ok) | |||
[...] | |||
</syntaxhighlight> | |||
Replace the hostnames and the TLSA hash according to your configuration. | |||
=== Users and inboxes === | |||
Creating credentials and inboxes for a specific account. The first command creates the user <code>postmaster@example.org</code> and will prompt for a password. | Creating credentials and inboxes for a specific account. The first command creates the user <code>postmaster@example.org</code> and will prompt for a password. | ||
Line 156: | Line 216: | ||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | {{file|/etc/nixos/configuration.nix|nix|<nowiki> | ||
{ options, lib, ... }: { | { options, lib, ... }: { | ||
services.maddy.config = builtins.replaceStrings ["msgpipeline local_routing {"] [''msgpipeline local_routing { | services.maddy.config = builtins.replaceStrings ["msgpipeline local_routing {"] [''msgpipeline local_routing { | ||
Line 165: | Line 223: | ||
} | } | ||
}''] options.services.maddy.config.default; | }''] options.services.maddy.config.default; | ||
services.rspamd = { | |||
enable = true; | |||
locals."dkim_signing.conf".text = '' | |||
selector = "default"; | |||
domain = "project-insanity.org"; | |||
path = "/var/lib/maddy/dkim_keys/$domain_$selector.key"; | |||
''; | |||
}; | |||
systemd.services.rspamd.serviceConfig.SupplementaryGroups = [ "maddy" ]; | |||
[...] | [...] | ||
Line 171: | Line 240: | ||
The second part in this example replaces a part in the default config of the Maddy module and inserts the rspamd check to the message pipeline as described in the [https://maddy.email/reference/checks/rspamd upstream documentation]. | The second part in this example replaces a part in the default config of the Maddy module and inserts the rspamd check to the message pipeline as described in the [https://maddy.email/reference/checks/rspamd upstream documentation]. | ||
== | The [[rspamd]] article also has some notes on how to achieve training for spam/ham mails using an additional helper script. | ||
=== Mail attachement size === | |||
The default max mail attachement size is set to 32MB, for a higher value (in this case 64MB) change the default configuration via this workaround | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ options, lib, ... }: { | |||
services.maddy.config = builtins.replaceStrings [ | |||
"dmarc yes" | |||
] [ | |||
''dmarc yes | |||
max_message_size 64M''] options.services.maddy.config.default; | |||
[...] | |||
</nowiki>}} | |||
=== Alias addresses === | |||
The following example will add an alias <code>mailA@example.org</code> for the local mail address <code>mailB@example.org</code> meaning that every mail send to <code>mailA</code> will get delivered to <code>mailB</code>. | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ options, lib, ... }: { | |||
services.maddy.config = builtins.replaceStrings [ | |||
"optional_step file /etc/maddy/aliases" | |||
] [ | |||
"optional_step static { | |||
entry mailA@example.org mailB@example.org | |||
}"] options.services.maddy.config.default; | |||
[...] | |||
</nowiki>}} | |||
== Tips & tricks == | |||
=== Test mail server === | === Test mail server === | ||
Line 226: | Line 330: | ||
Of course autoconfig.example.org domain should point to your server running the SSL enabled web service. | Of course autoconfig.example.org domain should point to your server running the SSL enabled web service. | ||
== Troubleshooting == | |||
=== TLS it not available or unauthenticated but required === | |||
This error occurs if the receiving mail server has a invalid or none TLS configuration. The default configuration of Maddy enforces a valid TLS connection to the remote server for delivery. If you want to disable this default policy, apply following configuration hack | |||
{{file|/etc/nixos/configuration.nix|nix|<nowiki> | |||
{ options, lib, ... }: { | |||
services.maddy.config = builtins.replaceStrings [ | |||
"min_tls_level encrypted" | |||
] [ | |||
"min_tls_level none"] options.services.maddy.config.default; | |||
[...] | |||
</nowiki>}} | |||
== See also == | == See also == | ||
* [https://maddy.email Maddy homepage and documentation] | * [https://maddy.email Maddy homepage and documentation] | ||
* [[Stalwart]], an open-source, all-in-one mail server solution that supports JMAP, IMAP4, and SMTP protocols | |||
* [https://nixos-mailserver.readthedocs.io/en/latest Simple NixOS Mailserver] | |||
* [[Imapsync]], useful tool to migrate mailboxes to a new server | |||
[[Category:Mail Server]] | [[Category:Mail Server]] | ||
[[Category:Server]] |