This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| computing:mailserver-trixie [2026/05/31 03:31] – oemb1905 | computing:mailserver-trixie [2026/08/31 00:07] (current) – oemb1905 | ||
|---|---|---|---|
| Line 11: | Line 11: | ||
| ------------------------------------------- | ------------------------------------------- | ||
| - | * [[https://nextcloud.haacksnetworking.org/ | + | * [[https://cloud.haacksnetworking.org/ |
| - | * [[https:// | + | * [[https:// |
| * [[https:// | * [[https:// | ||
| 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 lmtpdovecot_storage_version | + | protocols = imap lmtp |
| - | dovecot_config_version = 2.4 | + | dovecot_storage_version |
| + | dovecot_config_version = 2.4.1 | ||
| # If you upgraded from Bookworm, comment out dictionary | # If you upgraded from Bookworm, comment out dictionary | ||
| # dict { | # dict { | ||
| Line 224: | Line 226: | ||
| - | < | + | < |
| - | mail_driver = maildirmail_path | + | mail_driver = maildir |
| + | mail_path | ||
| + | mail_inbox_path | ||
| </ | </ | ||
| Make sure that the dovecot user and the simple UNIX users are both part of the mail group. Remember, this tutorial does not use virtual users and/or an associated database. This tutorial uses simple UNIX user names which means the yourusername listed below will have the email '' | Make sure that the dovecot user and the simple UNIX users are both part of the mail group. Remember, this tutorial does not use virtual users and/or an associated database. This tutorial uses simple UNIX user names which means the yourusername listed below will have the email '' | ||
| - | sudo adduser | + | sudo adduser |
| + | sudo adduser dovecot | ||
| + | sudo adduser yourusername mail | ||
| 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 246: | 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 | ||
| </ | </ | ||
| It's now time to instruct dovecot as to what authorization mechanisms to accept. Remember, plain login, contrary to popular belief, is not in any way insecure. Remeber that they both use Base64 encoding to begin with, which is then wrapped in TLS. Therefore, as long as you enforce TLS, there' | It's now time to instruct dovecot as to what authorization mechanisms to accept. Remember, plain login, contrary to popular belief, is not in any way insecure. Remeber that they both use Base64 encoding to begin with, which is then wrapped in TLS. Therefore, as long as you enforce TLS, there' | ||
| - | < | + | < |
| auth_username_format = %{user|username|lower} | auth_username_format = %{user|username|lower} | ||
| auth_mechanisms = plain login | auth_mechanisms = plain login | ||
| Line 259: | 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 268: | Line 275: | ||
| Add SASL listener in ''/ | Add SASL listener in ''/ | ||
| - | < | + | < |
| service auth { | service auth { | ||
| unix_listener / | unix_listener / | ||
| Line 287: | Line 294: | ||
| </ | </ | ||
| - | Similarly, for large IMAP folders, you also want to adjust IMAP's logic to provide 256k (vs. 64k) to each single IMAP command. Additionally, | + | Similarly, for large IMAP folders, you also want to adjust IMAP's logic to provide 256k (vs. 64k) to each single IMAP command. Additionally, |
| < | < | ||
| Line 293: | Line 300: | ||
| imap_max_line_length = 256k | imap_max_line_length = 256k | ||
| mail_max_userip_connections = 50 | mail_max_userip_connections = 50 | ||
| - | imap_idle_notify_interval = 30s | + | imap_idle_notify_interval = 15s |
| } | } | ||
| </ | </ | ||
| - | 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 | ||
| </ | </ | ||
| 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 |
| + | openssl s_client -connect mail.yourdomain.com: | ||
| + | openssl | ||
| + | swaks --tls --server mail.yourdomain.com -p 587 | ||
| + | swaks --tls --server mail.yourdomain.com -p 465 | ||
| </ | </ | ||
| Line 323: | Line 335: | ||
| As with elsewhere, this tutorial does not use any of the policies for rejecting email - everything is accepted. As your server matures and you complete testing, you can optionally harden your server' | As with elsewhere, this tutorial does not use any of the policies for rejecting email - everything is accepted. As your server matures and you complete testing, you can optionally harden your server' | ||
| - | < | + | < |
| #spf policy\ | #spf policy\ | ||
| - | policyd-spf unix - n n - 0 spawn\ | + | policyd-spf |
| - | user=policyd-spf argv=/ | + | user=policyd-spf argv=/ |
| </ | </ | ||
| 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 = permit_mynetworks, | + | smtpd_recipient_restrictions = |
| + | | ||
| + | | ||
| + | | ||
| + | reject_non_fqdn_recipient, | ||
| + | reject_unknown_recipient_domain, | ||
| + | | ||
| </ | </ | ||
| Line 344: | Line 362: | ||
| Since I just took care of recipient restrictions, | Since I just took care of recipient restrictions, | ||
| - | < | + | < |
| smtpd_sender_restrictions = | smtpd_sender_restrictions = | ||
| - | permit_mynetworks, | + | |
| - | permit_sasl_authenticated, | + | permit_sasl_authenticated, |
| - | # | + | # |
| - | # | + | # |
| - | # | + | # |
| - | reject_unauthenticated_sender_login_mismatch, | + | reject_unauthenticated_sender_login_mismatch, |
| - | reject_sender_login_mismatch, | + | reject_sender_login_mismatch, |
| - | permit | + | |
| + | | ||
| </ | </ | ||
| + | |||
| + | The sender_access file is super helpful for repeat offenders. Sure, you can also just blacklist those in sieve rules, but that means that they still arrive and fill up your Junk folder. In some cases, spammers will send 100s of the same message per day. In those cases, it is helpful to stop them at the gates with postfix' | ||
| + | |||
| + | nano / | ||
| + | < | ||
| + | < | ||
| + | < | ||
| + | sudo postmap / | ||
| + | sudo postfix reload | ||
| + | sudo systemctl restart postfix | ||
| Now that the SPF/ | Now that the SPF/ | ||
| - | < | + | < |
| sudo apt install opendkim opendkim-tools | sudo apt install opendkim opendkim-tools | ||
| sudo adduser postfix opendkim | sudo adduser postfix opendkim | ||
| Line 365: | 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 378: | Line 407: | ||
| It's now time to create the keys: | It's now time to create the keys: | ||
| - | < | + | < |
| sudo mkdir -p / | sudo mkdir -p / | ||
| sudo chown -R opendkim: | sudo chown -R opendkim: | ||
| sudo chmod 711 / | sudo chmod 711 / | ||
| - | sudo mkdir / | ||
| - | sudo opendkim-genkey -b 2048 -d yourdomain.com -D / | ||
| - | sudo chown opendkim: | ||
| - | sudo chmod 600 / | ||
| </ | </ | ||
| 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 399: | Line 424: | ||
| default._domainkey.yourdomain.com yourdomain.com: | default._domainkey.yourdomain.com yourdomain.com: | ||
| - | 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 407: | Line 432: | ||
| </ | </ | ||
| - | Use the built-in tool to test your DKIM keypair: | + | Now, cut the keys: |
| - | sudo opendkim-testkey | + | |
| + | | ||
| + | sudo chown opendkim: | ||
| + | sudo chmod 600 / | ||
| It's now time to build your last DNS record. To do that, you need your public key you created above. To view that on the CLI, run the cat command below. You then take that output to your DNS host of choice, and create a TXT record containing this value. In the subdomain field, you enter your selector, i.e., default._domainkey and in the target, you enter the output of the command below. | It's now time to build your last DNS record. To do that, you need your public key you created above. To view that on the CLI, run the cat command below. You then take that output to your DNS host of choice, and create a TXT record containing this value. In the subdomain field, you enter your selector, i.e., default._domainkey and in the target, you enter the output of the command below. | ||
| sudo cat / | sudo cat / | ||
| + | |||
| + | Once your DNS record for DKIM is created, use the built-in tool to test the record: | ||
| + | |||
| + | sudo opendkim-testkey -d yourdomain.com -s default -vvv | ||
| Okay, now that your keypair for smtp has been created and DNS updated, it's a good time to create the server' | Okay, now that your keypair for smtp has been created and DNS updated, it's a good time to create the server' | ||
| Line 430: | 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 437: | 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 451: | Line 483: | ||
| Similarly to the DKIM policy, we need to give postfix permissions to the DMARC tooling and socket. It's also required to add opendmarc to the postfix group: | Similarly to the DKIM policy, we need to give postfix permissions to the DMARC tooling and socket. It's also required to add opendmarc to the postfix group: | ||
| - | < | + | < |
| sudo mkdir -p / | sudo mkdir -p / | ||
| sudo chown opendmarc: | sudo chown opendmarc: | ||
| Line 461: | 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 479: | 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 487: | 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 495: | 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 515: | 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 529: | 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 561: | Line 602: | ||
| This basic configuration shows you where to place the rules/ | This basic configuration shows you where to place the rules/ | ||
| - | < | + | < |
| cd /var/www | cd /var/www | ||
| wget https:// | wget https:// | ||
| Line 574: | Line 615: | ||
| Obviously, go check the git repo and make sure to download the latest stable version. Roundcube requires a database, so let's set that up: | Obviously, go check the git repo and make sure to download the latest stable version. Roundcube requires a database, so let's set that up: | ||
| - | < | + | < |
| sudo mysql -u root | sudo mysql -u root | ||
| CREATE DATABASE roundcube DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; | CREATE DATABASE roundcube DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci; | ||
| Line 589: | Line 630: | ||
| Earlier in the tutorial, you were instructed to setup a vhost for '' | Earlier in the tutorial, you were instructed to setup a vhost for '' | ||
| - | < | + | < |
| < | < | ||
| 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 617: | Line 658: | ||
| After that's done, edit the vhost-mail-le.conf file with something like the following: | After that's done, edit the vhost-mail-le.conf file with something like the following: | ||
| - | < | + | < |
| < | < | ||
| < | < | ||
| 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 646: | Line 687: | ||
| Since the certificate was already created, these configs can just be dropped in to the http vhost and https vhost, respectively. These two vhosts were created earlier by you (http) and subsequently by Let's Encrypt (https). It's now time to connect Roundcube to the database that was created earlier: | Since the certificate was already created, these configs can just be dropped in to the http vhost and https vhost, respectively. These two vhosts were created earlier by you (http) and subsequently by Let's Encrypt (https). It's now time to connect Roundcube to the database that was created earlier: | ||
| - | < | + | < |
| cd / | cd / | ||
| sudo cp config.inc.php.sample config.inc.php | sudo cp config.inc.php.sample config.inc.php | ||
| Line 660: | Line 701: | ||
| In addition to configuring the database and renaming the sample config, it's imperative to edit the plugins block at the end of the primary configuration as well. Add and/or replace the bottom plugin block as follows: | In addition to configuring the database and renaming the sample config, it's imperative to edit the plugins block at the end of the primary configuration as well. Add and/or replace the bottom plugin block as follows: | ||
| - | < | + | < |
| $config[' | $config[' | ||
| ' | ' | ||
| Line 670: | Line 711: | ||
| ' | ' | ||
| ' | ' | ||
| - | ' | + | |
| ' | ' | ||
| ' | ' | ||
| Line 699: | Line 740: | ||
| At this point, you should be able to log in to mail.haacksnetworking.org / mail.domain.com using a common web browser and your credentials. Your user name is the UNIX user name, i.e., only the handle without the domain. So, my user name is jonathan, for example ... and without haacksnetworking.org at the end. Your password is whatever you adduser yourusername specified when creating your simple UNIX user. At this point, you want to open your web browser and login. Head to the Filters section under Settings. Click the cog at the top and select Edit Filter Set. In the block to the right, replace the contents with the following: | At this point, you should be able to log in to mail.haacksnetworking.org / mail.domain.com using a common web browser and your credentials. Your user name is the UNIX user name, i.e., only the handle without the domain. So, my user name is jonathan, for example ... and without haacksnetworking.org at the end. Your password is whatever you adduser yourusername specified when creating your simple UNIX user. At this point, you want to open your web browser and login. Head to the Filters section under Settings. Click the cog at the top and select Edit Filter Set. In the block to the right, replace the contents with the following: | ||
| - | < | + | < |
| require [" | require [" | ||
| # rule: | # rule: | ||
| Line 714: | Line 755: | ||
| } | } | ||
| # rule: | # rule: | ||
| - | if anyof (header :contains | + | if anyof (header :matches |
| { | { | ||
| fileinto " | fileinto " | ||
| Line 727: | Line 768: | ||
| As you can see in the asset above, you now have access to refined sieve rules for each user. Once I decided that I needed or wanted user-level spam controls, it no longer made sense for me to manage this exclusively on the CLI. For this reason, I added Roundcube and began managing spam for email accounts individually. When Trixie came out, Dovecot' | As you can see in the asset above, you now have access to refined sieve rules for each user. Once I decided that I needed or wanted user-level spam controls, it no longer made sense for me to manage this exclusively on the CLI. For this reason, I added Roundcube and began managing spam for email accounts individually. When Trixie came out, Dovecot' | ||
| - | < | + | < |
| # Comment out the old block: | # Comment out the old block: | ||
| #plugin { | #plugin { | ||
| Line 739: | Line 780: | ||
| active_path = ~/ | active_path = ~/ | ||
| } | } | ||
| + | </ | ||
| + | |||
| + | Lastly, Roundcube is a web gui. So, it is also important that your php handler is optimized and configured with more memory and extra fpm servers. I make the following php adjustments for snappier response time. In ''/ | ||
| + | |||
| + | < | ||
| + | memory_limit = 1G | ||
| + | max_execution_time = 300 | ||
| + | max_input_time = 300 | ||
| + | </ | ||
| + | |||
| + | And, finally, in ''/ | ||
| + | |||
| + | < | ||
| + | pm = dynamic | ||
| + | pm.max_children = 200 | ||
| + | pm.start_servers = 20 | ||
| + | pm.min_spare_servers = 10 | ||
| + | pm.max_spare_servers = 20 | ||
| + | pm.max_requests = 500 | ||
| + | request_terminate_timeout = 0 | ||
| </ | </ | ||
| ====== 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 |
| - | < | + | < |
| / | / | ||
| missingok | missingok | ||
| Line 758: | Line 819: | ||
| You need to make sure to comment out or remove #mail.log from ''/ | You need to make sure to comment out or remove #mail.log from ''/ | ||
| - | < | + | < |
| #!/bin/sh | #!/bin/sh | ||
| #/ | #/ | ||
| Line 783: | Line 844: | ||
| Some of the spam assassin tooling that uses RBL will not work unless you use your own recursive DNS instead of, for example, '' | Some of the spam assassin tooling that uses RBL will not work unless you use your own recursive DNS instead of, for example, '' | ||
| - | < | + | < |
| server: | server: | ||
| # Bind to localhost only | # Bind to localhost only | ||
| Line 862: | Line 923: | ||
| Next, open up ''/ | Next, open up ''/ | ||
| - | < | + | < |
| / | / | ||
| daily | daily | ||
| Line 876: | Line 937: | ||
| Next, disable systemd' | Next, disable systemd' | ||
| - | < | + | < |
| systemctl disable --now unbound-resolvconf.service | systemctl disable --now unbound-resolvconf.service | ||
| sed -Ei ' | sed -Ei ' | ||
| Line 926: | Line 987: | ||
| In the .xml file, put the following, adjusting for '' | In the .xml file, put the following, adjusting for '' | ||
| - | < | + | < |
| <?xml version=" | <?xml version=" | ||
| < | < | ||
| Line 985: | Line 1046: | ||
| The options below are results of small things that came up while using my own server over the last 5 years or so. First, I noticed that clients would not set up the standard directories and it turns out you need to tell dovevot to do that over in ''/ | The options below are results of small things that came up while using my own server over the last 5 years or so. First, I noticed that clients would not set up the standard directories and it turns out you need to tell dovevot to do that over in ''/ | ||
| - | < | + | < |
| mailbox Drafts { | mailbox Drafts { | ||
| auto = create | auto = create | ||
| Line 1002: | 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 1022: | Line 1083: | ||
| -- -- -- -- Miscellaneous Issues -- -- -- -- | -- -- -- -- Miscellaneous Issues -- -- -- -- | ||
| - | To test sieve logic and rules, do the following: | + | To test sieve' |
| + | su - username | ||
| + | cd ~/sieve | ||
| + | spamassassin -t -D < Amazon1.eml | ||
| + | # this ^^ gives you the headers / spamassassin scores in stdout | ||
| + | sieve-test -D -e roundcube.sieve Amazon3.eml | ||
| + | # this ^^ tests your sieve logic to see if the email goes in ham or spam | ||
| + | In the output that follows, look for something like the below. I put example output for each command above, respectively: | ||
| + | < | ||
| + | Content analysis details: | ||
| + | |||
| + | pts rule name description | ||
| + | ---- ---------------------- -------------------------------------------------- | ||
| + | 0.8 DKIM_ADSP_ALL | ||
| + | 0.0 SPF_HELO_NONE | ||
| + | -0.0 SPF_PASS | ||
| + | 0.2 BAYES_999 | ||
| + | [score: 1.0000] | ||
| + | 3.5 BAYES_99 | ||
| + | [score: 1.0000] | ||
| + | 2.0 HEADER_FROM_DIFFERENT_DOMAINS From and EnvelopeFrom 2nd level mail | ||
| + | domains are different | ||
| + | 2.1 HTML_IMAGE_ONLY_12 | ||
| + | 0.0 HTML_EXTRA_CLOSE | ||
| + | 0.1 MIME_HTML_ONLY | ||
| + | 0.0 HTML_MESSAGE | ||
| + | 2.0 RDNS_DYNAMIC | ||
| + | dynamic-looking rDNS | ||
| + | 0.0 HTML_SHORT_LINK_IMG_2 | ||
| + | 3.6 HTML_TAG_BALANCE_CENTER Malformatted HTML | ||
| + | 0.4 HTML_MIME_NO_HTML_TAG | ||
| + | 1.0 GOOG_STO_IMG_HTML | ||
| + | URIBL | ||
| + | 1.2 DMARC_QUAR | ||
| + | 0.0 T_REMOTE_IMAGE | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | sieve-test: Debug: sieve: Commit fileinto action | ||
| + | sieve-test: Debug: sieve: fileinto action: Commit storing into mailbox ' | ||
| + | sieve-test: Info: sieve: msgid=< | ||
| + | info: msgid=< | ||
| + | sieve-test: Debug: sieve: Finished finalizing actions (status=ok, keep=none, committed=yes) | ||
| + | </ | ||
| ====== Part IX - What's next? ====== | ====== Part IX - What's next? ====== | ||
| Line 1039: | Line 1143: | ||
| I rewrote the mail server tutorial for the presentation [[https:// | I rewrote the mail server tutorial for the presentation [[https:// | ||
| - | --- // | + | --- // |