This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:mailserver-trixie [2026/07/31 16:46] – oemb1905 | computing:mailserver-trixie [2026/08/31 00:07] (current) – oemb1905 | ||
|---|---|---|---|
| Line 70: | Line 70: | ||
| sudo apt update && sudo apt upgrade -y | sudo apt update && sudo apt upgrade -y | ||
| - | sudo apt install mailutils postfix ufw fail2ban | + | sudo apt install mailutils postfix ufw fail2ban apache2 php8.4-fpm php8.4-mysql php8.4-curl php8.4-gd php8.4-mbstring php8.4-xml php8.4-zip dovecot-core dovecot-imapd dovecot-lmtpd |
| It's also important that that the host knows how to identify itself properly. Let's open it up ''/ | It's also important that that the host knows how to identify itself properly. Let's open it up ''/ | ||
| - | < | + | < |
| 127.0.0.1 localhost | 127.0.0.1 localhost | ||
| 127.0.1.1 mail.haacksnetworking.org haacksnetworking | 127.0.1.1 mail.haacksnetworking.org haacksnetworking | ||
| Line 131: | Line 131: | ||
| Make sure to create '' | Make sure to create '' | ||
| - | < | + | < |
| submission inet n - y - - smtpd | submission inet n - y - - smtpd | ||
| -o syslog_name=postfix/ | -o syslog_name=postfix/ | ||
| Line 155: | Line 155: | ||
| The changes above add service definitions and configurations for smtps (465) and submission (587), both of which handle mail submission, or the sending of email. Examples of these configurations can be found in ''/ | The changes above add service definitions and configurations for smtps (465) and submission (587), both of which handle mail submission, or the sending of email. Examples of these configurations can be found in ''/ | ||
| - | < | + | < |
| # A) Leave the following upper-block defaults | # A) Leave the following upper-block defaults | ||
| smtpd_banner = $myhostname ESMTP $mail_name (Debian/ | smtpd_banner = $myhostname ESMTP $mail_name (Debian/ | ||
| Line 202: | Line 202: | ||
| inet_protocols = all | inet_protocols = all | ||
| message_size_limit = 52428800 | message_size_limit = 52428800 | ||
| + | cyrus_sasl_config_path = / | ||
| </ | </ | ||
| Line 212: | Line 213: | ||
| In order for dovecot to work, we need to specify which protocols we allow, the mail directory location, ensure that dovecot is a member of the mail group, and enable lmtp the for delivery agent. Lmtp is a local delivery agent and hands off processed incoming emails to the storage directories without requiring external authentication. This ensures everything is delivered locally, or within the hardened host. Larger distributed email systems require smtp for network hand offs between servers, but that's not required or helpful for mail server self-hosters. Open up ''/ | In order for dovecot to work, we need to specify which protocols we allow, the mail directory location, ensure that dovecot is a member of the mail group, and enable lmtp the for delivery agent. Lmtp is a local delivery agent and hands off processed incoming emails to the storage directories without requiring external authentication. This ensures everything is delivered locally, or within the hardened host. Larger distributed email systems require smtp for network hand offs between servers, but that's not required or helpful for mail server self-hosters. Open up ''/ | ||
| - | < | + | < |
| protocols = imap lmtp | protocols = imap lmtp | ||
| dovecot_storage_version = 2.4.1 | dovecot_storage_version = 2.4.1 | ||
| Line 225: | Line 226: | ||
| - | < | + | < |
| mail_driver = maildir | mail_driver = maildir | ||
| mail_path = ~/Maildir | mail_path = ~/Maildir | ||
| Line 239: | Line 240: | ||
| It is required that lmtp be configured for use with dovecot. To do that, edit ''/ | It is required that lmtp be configured for use with dovecot. To do that, edit ''/ | ||
| - | < | + | < |
| service lmtp { | service lmtp { | ||
| unix_listener / | unix_listener / | ||
| Line 251: | Line 252: | ||
| Postfix also needs to know the delivery agent that's being used, otherwise it won't know what service to which it should send incoming email. In short, lmtp hands off emails from postfix' | Postfix also needs to know the delivery agent that's being used, otherwise it won't know what service to which it should send incoming email. In short, lmtp hands off emails from postfix' | ||
| - | < | + | < |
| mailbox_transport = lmtp: | mailbox_transport = lmtp: | ||
| smtputf8_enable = no | smtputf8_enable = no | ||
| Line 265: | Line 266: | ||
| Now, let's enforce ssl so that the plain and login mechanisms above are wrapped - end to end - in TLS handshakes. It is also important to explicitly define the least secure and/or oldest TLS handshake your server will permit. Additionally, | Now, let's enforce ssl so that the plain and login mechanisms above are wrapped - end to end - in TLS handshakes. It is also important to explicitly define the least secure and/or oldest TLS handshake your server will permit. Additionally, | ||
| - | < | + | < |
| ssl = required | ssl = required | ||
| ssl_server_cert_file = / | ssl_server_cert_file = / | ||
| Line 274: | Line 275: | ||
| Add SASL listener in ''/ | Add SASL listener in ''/ | ||
| - | < | + | < |
| service auth { | service auth { | ||
| unix_listener / | unix_listener / | ||
| Line 303: | Line 304: | ||
| </ | </ | ||
| - | Lastly, before testing, make sure that you only authorize your mynetworks and properly authenticated users. Failing to do this will mean your server could potentially be used for public relay. This block rejects any unauthenticated senders (besides localhost) and requires senders to be authenticated (or to be localhost) while only permitting incoming email directed to '' | + | Lastly, before testing, make sure that you only authorize your mynetworks and properly authenticated users. Failing to do this will mean your server could potentially be used for public relay. This block rejects any unauthenticated senders (besides localhost) and requires senders to be authenticated (or to be localhost) while only permitting incoming email directed to '' |
| - | < | + | < |
| smtpd_sender_restrictions = permit_mynetworks, | smtpd_sender_restrictions = permit_mynetworks, | ||
| smtpd_recipient_restrictions = permit_mynetworks, | smtpd_recipient_restrictions = permit_mynetworks, | ||
| Line 312: | Line 313: | ||
| At this time, the bare minimum requirements are in place for sending and receiving email. You can either fire up Thunderbird and field test it all, or use swaks, ncat, telnet, or openssl to test the TLS handshakes. Here's the ones I use in addition to field testing with Thunderbird: | At this time, the bare minimum requirements are in place for sending and receiving email. You can either fire up Thunderbird and field test it all, or use swaks, ncat, telnet, or openssl to test the TLS handshakes. Here's the ones I use in addition to field testing with Thunderbird: | ||
| - | < | + | < |
| openssl s_client -connect mail.yourdomain.com: | openssl s_client -connect mail.yourdomain.com: | ||
| openssl s_client -connect mail.yourdomain.com: | openssl s_client -connect mail.yourdomain.com: | ||
| Line 342: | Line 343: | ||
| After that, open up ''/ | After that, open up ''/ | ||
| - | < | + | < |
| - | #spf incoming policy and recipient restrictions\ | + | #spf incoming policy and recipient restrictions |
| - | policyd-spf_time_limit = 3600\ | + | policyd-spf_time_limit = 3600 |
| smtpd_recipient_restrictions = | smtpd_recipient_restrictions = | ||
| permit_mynetworks, | permit_mynetworks, | ||
| Line 393: | Line 394: | ||
| Once that's done, it's time to open ''/ | Once that's done, it's time to open ''/ | ||
| - | < | + | < |
| Canonicalization relaxed/ | Canonicalization relaxed/ | ||
| Mode sv | Mode sv | ||
| Line 414: | Line 415: | ||
| After creating the keys, edit the signing table so that outgoing emails can verify against the keypair. Open up ''/ | After creating the keys, edit the signing table so that outgoing emails can verify against the keypair. Open up ''/ | ||
| - | < | + | < |
| - | '*@yourdomain.com default._domainkey.yourdomain.com' | + | *@yourdomain.com default._domainkey.yourdomain.com |
| - | '*@*.yourdomain.com default._domainkey.yourdomain.com' | + | *@*.yourdomain.com default._domainkey.yourdomain.com |
| </ | </ | ||
| Line 425: | Line 426: | ||
| Lastly, instruct you server to trust only localhost and your domain. Open up ''/ | Lastly, instruct you server to trust only localhost and your domain. Open up ''/ | ||
| - | < | + | < |
| 127.0.0.1\ | 127.0.0.1\ | ||
| localhost\ | localhost\ | ||
| Line 461: | Line 462: | ||
| Now that the server' | Now that the server' | ||
| - | < | + | < |
| milter_default_action = accept | milter_default_action = accept | ||
| milter_protocol = 6 | milter_protocol = 6 | ||
| Line 468: | Line 469: | ||
| </ | </ | ||
| - | The most important line is the uppermost line, which specifies that email should not be rejected as a result of leveraging the policy. Again, this ensures that spam assassin has what it needs to help users sort and organize email, without the possibility of phantom rejections, prohibiting email from having ever arrived in your inbox. After your DKIM keypair and DKIM policy are setup, you can setup a DMARC policy as well. Install the policy with sudo apt install opendmarc. After it installs, open up ''/ | + | The most important line is the uppermost line, which specifies that email should not be rejected as a result of leveraging the policy. Again, this ensures that spam assassin has what it needs to help users sort and organize email, without the possibility of phantom rejections, prohibiting email from having ever arrived in your inbox. After your DKIM keypair and DKIM policy are setup, you can setup a DMARC policy as well. Install the policy with '' |
| - | < | + | < |
| AuthservID OpenDMARC | AuthservID OpenDMARC | ||
| TrustedAuthservIDs mail.yourdomain.com | TrustedAuthservIDs mail.yourdomain.com | ||
| Line 492: | Line 493: | ||
| Similarly to SPF and DKIM, it's essential to define the policy in the main postfix configuration file. Open up ''/ | Similarly to SPF and DKIM, it's essential to define the policy in the main postfix configuration file. Open up ''/ | ||
| - | < | + | < |
| #dmarc policy | #dmarc policy | ||
| milter_default_action = accept | milter_default_action = accept | ||
| Line 510: | Line 511: | ||
| First, let's add sieve to the local delivery agent over in / | First, let's add sieve to the local delivery agent over in / | ||
| - | < | + | < |
| protocol lda { | protocol lda { | ||
| mail_plugins = $mail_plugins sieve | mail_plugins = $mail_plugins sieve | ||
| Line 518: | Line 519: | ||
| It is also imperative that LMTP be configured for using sieve as well. Head over to ''/ | It is also imperative that LMTP be configured for using sieve as well. Head over to ''/ | ||
| - | < | + | < |
| protocol lmtp { | protocol lmtp { | ||
| mail_plugins = quota sieve | mail_plugins = quota sieve | ||
| Line 526: | Line 527: | ||
| As with any service, it's essential to configure postfix to use it. So, head to ''/ | As with any service, it's essential to configure postfix to use it. So, head to ''/ | ||
| - | < | + | < |
| milter_default_action = accept | milter_default_action = accept | ||
| milter_protocol = 6 | milter_protocol = 6 | ||
| Line 546: | Line 547: | ||
| Sieve is already enabled in dovecot and postfix. That was done up above. Now, the tutorial is discussing how to leverage the sieve syntax or language to get desired user results for incoming email. The most basic way to do this is by setting up a global, or server-wide rule, that filters emails before dovecot, via lmtp, delivers the emails to their final destination. This is done by spam assassin adding custom fields and scoring to incoming email headers. The sieve plugin assesses these headers and then makes the correct determination for the final destination, | Sieve is already enabled in dovecot and postfix. That was done up above. Now, the tutorial is discussing how to leverage the sieve syntax or language to get desired user results for incoming email. The most basic way to do this is by setting up a global, or server-wide rule, that filters emails before dovecot, via lmtp, delivers the emails to their final destination. This is done by spam assassin adding custom fields and scoring to incoming email headers. The sieve plugin assesses these headers and then makes the correct determination for the final destination, | ||
| - | | + | < |
| + | #sieve_before = / | ||
| - | Now, create the file that you just referenced above in '' | + | #modern trixie way |
| + | sieve_script SpamToJunk { | ||
| + | type = before | ||
| + | path = / | ||
| + | } | ||
| + | </ | ||
| - | < | + | Now, create the file that you just referenced above in ''/ |
| + | |||
| + | < | ||
| require " | require " | ||
| if header :contains " | if header :contains " | ||
| Line 560: | Line 569: | ||
| Load the rule by issuing the '' | Load the rule by issuing the '' | ||
| - | < | + | < |
| report_contact webmaster@yourdomain.com | report_contact webmaster@yourdomain.com | ||
| required_score 5.0 | required_score 5.0 | ||
| report_safe 0 | report_safe 0 | ||
| - | ifplugin Mail:: | + | ifplugin Mail:: |
| + | endif Mail:: | ||
| # uncomment the line below once unbound is working (optional) | # uncomment the line below once unbound is working (optional) | ||
| # dns_server 127.0.0.1score MISSING_FROM 5.0 | # dns_server 127.0.0.1score MISSING_FROM 5.0 | ||
| Line 624: | Line 634: | ||
| ServerName mail.domain.com | ServerName mail.domain.com | ||
| ServerAdmin email@email.com | ServerAdmin email@email.com | ||
| - | DocumentRoot / | + | DocumentRoot / |
| ErrorLog ${APACHE_LOG_DIR}/ | ErrorLog ${APACHE_LOG_DIR}/ | ||
| CustomLog ${APACHE_LOG_DIR}/ | CustomLog ${APACHE_LOG_DIR}/ | ||
| Line 653: | Line 663: | ||
| ServerName mail.domain.com | ServerName mail.domain.com | ||
| ServerAdmin email@email.com | ServerAdmin email@email.com | ||
| - | DocumentRoot / | + | DocumentRoot / |
| ErrorLog ${APACHE_LOG_DIR}/ | ErrorLog ${APACHE_LOG_DIR}/ | ||
| CustomLog ${APACHE_LOG_DIR}/ | CustomLog ${APACHE_LOG_DIR}/ | ||
| Line 701: | Line 711: | ||
| ' | ' | ||
| ' | ' | ||
| - | ' | + | |
| ' | ' | ||
| ' | ' | ||
| Line 794: | Line 804: | ||
| ====== Part V - Setting up pflogsumm ====== | ====== Part V - Setting up pflogsumm ====== | ||
| - | It's important to be able to monitor how your setup is performing and what is or is not working correctly. No better way to do that than to get some analytics emailed to you each day. To do that, let's install pflogsumm and use rsyslog for logging. Install the packages sudo apt install pflogsumm rsyslog and then create the log rotation rule over in ''/ | + | It's important to be able to monitor how your setup is performing and what is or is not working correctly. No better way to do that than to get some analytics emailed to you each day. To do that, let's install pflogsumm and use rsyslog for logging. Install the packages |
| < | < | ||
| Line 1053: | Line 1063: | ||
| Once you edited the file, load the changes with sudo postmap / | Once you edited the file, load the changes with sudo postmap / | ||
| - | Another thing I researched when reviewing Linux Babe's tutorial, but ultimately rejected doing was body and header inspection. To do that, install postfix' | + | Another thing I researched when reviewing Linux Babe's tutorial, but ultimately rejected doing was body and header inspection. To do that, install postfix' |
| header_checks = pcre:/ | header_checks = pcre:/ | ||
| Line 1133: | Line 1143: | ||
| I rewrote the mail server tutorial for the presentation [[https:// | I rewrote the mail server tutorial for the presentation [[https:// | ||
| - | --- // | + | --- // |