Install Postfix/Dovecot e-mail Server on Amazon Linux2/SES

 In Amazon AWS

PLEASE SEE MY CURRENT POST FOR LINUX 2022 INSTALLATION

Install a Secure TLS/SMTP IMAP e-mail Server on Amazon Linux2

Software: SASL, PAM, POSTFIX, DOVECOT, SSL, ROUNDCUBE

An END-TO-END Solution

This is a detailed discussion for an end-to-end installation of a basic/introductory e-mail server on Amazon Linux.

I looked at this on and off for 2 years, finally having a working installation. I gave up many times. There is no end-to-end article on the Internet for this installation, but some very important sections of information from various authors. I do not recommend these configurations for a production server. Others spend millions of dollars to do that for us, so we should be using services like Amazon Workmail or MS Exchange and so on.

Having said that, I assert this service will make use of a pre-configured and tested SES service utilising an S3 bucket, Lambda function(s), Amazon’s anti-spam and DKIM/SPF, DMARC security. This means the headers of our final e-mails will be professional. We will also assume from my other installation notes you know how to install Linux2 (see my old Linux2 notes on the bottom of the Linux2022 installation page), and S3FS to do an “nfs-style” mount of the inbound e-mail bucket.

First Notes

Disclaimers

This article is not using production-strength or advanced configurations. It shows the basic installation as up and running only as a technical exercise for one e-mail user and no aliases or vhosts etc. It will use shawlw.me as the example domain name, which is okay as I only use this name from time to time for testing. There is no discussion of ongoing problems that may arise in the real world.

The end-to-end solution contains many configurations I personally do not understand or have expertise in. They are simply given as a working model, therefore some configs may not be needed or could be different.

Prerequisites

The service will need the SES framework up and running. We will have incoming e-mails going into an S3 bucket, as there is no other choice. These are transferred to the INBOX. SES also permits the outgoing e-mails.

We will configure Route53 DNS appropriately.

For the purposes of this exercise, we will not create a hostname called imap.shawlw.me as that would require an SSL certificate for shawlw.me, www.shawlw.me, and imap.shawlw.me. If we were doing this, we would test DNS entries for imap.shawlw.me to point to the same IP Address as shawlw.me (another A record) and an MX record to “10 shawlw.me” or imap.shawlw.me – I have not tested.

We are using a Comodo Store Postive SSL certificate, the lowest cost available, rather than letsencrypt. You may test with letsencrypt but the Comodo (or sertigo) would assure the certificate is valid and not produce incompatibility errors when testing.

We will configure a webserver with ROUNDCUBEMAIL for https://shawlw.me/roundcubemail in order to send and receive emails on the web interface.

We will configure Apple mail.app on an iMac to send and receive e-mails.

Notes

I will show the configurations here for Linux2, and later look at any changes or issues with Linux 2022. I have some concerns still to test on Linux 2022. I’d like to point out that the core of the work uses Dovecot for the imap service, so there is no use of cyrus-imapd at all. Cyrus itself is still in use though alongside dovecot.

Configurations and testing for e-mail are huge. Advanced configurations are another direction. As mentioned, I gave up on all this many times. One person’s Internet article may show what works for them on their Linux system, but not cover Amazon, or may only show parts of their work.

We will not look at POP3 email, only IMAP.

PART 1 – Packages and Configurations

Basic Configurations

yum packages & essential configurations

Simply work through these…

[Some of these are not needed on Linux2]

yum -y install automake fuse fuse-devel gcc-c++ git libcurl-devel libxml2-devel make openssl-devel
yum -y install bison flex gettext-devel 
yum -y install pam-devel dovecot
yum -y install telnet

Notes:

We have to configure current version of Mariadb for Roundcube email. Easier not to configure mariadb installation until these steps are completed.

techviewleo.com/how-to-install-mariadb-server-on-amazon-linux/

We will be using AUTH with plain and login rather than use of cram-md5 and/or digest-md5.

Telnet testing will not show AUTH to these items, but it will be using plain/login even if the apparent details do not show it.

Linux 2022 notes:
You would need
www.dovecot.org/download/
dnf -y install bison flex gettext-devel
dnf -y install postfix
You woud then make the dovecot installation with SSL as a required option and ln -s a link to /etc/dovecot for ease of use.
adduser dovecot
adduser dovenull (without any passwords)
I can add more info on this later.
In linux2022, we have to edit the file dovecot.service to say ProtectSystem=false. This is vital:

cd /etc/systemd/system
ln -s /usr/lib/systemd/system/dovecot.service dovecot.service
cd /usr/lib/systemd/system
ls
vi dovecot.service

Sometimes when restarting a service we are notified to use the command: systemctl daemon-reload
I prefer using a shell script for postfix and dovecot:

#!/bin/sh
echo "Stop Postfix Dovecot"
systemctl stop postfix
systemctl stop dovecot
echo "Start Postfix Dovecot"
systemctl start dovecot
systemctl start postfix
echo "Status Postfix"
systemctl status postfix
echo "Status Dovecot"
systemctl status dovecot
echo "TESTSASLAUTHD"
testsaslauthd -u laurie -p myAloha.12
exit

And manually: systemctl restart saslauthd. postfix, dovecot, saslauthd need to be systemctl enabled.
I also like to check the status of systems with systemctl status postfix -l and so on. When we try external access to our new services, these status commands can show immediate problems,
as well as various log files which are a bit awkward to work with.
The EC2 Instance security group has in addition to the usual ports, the following: (these cater for imap, pop, smtp)
587
25
993
80
110
143
443
995
465

Create your mailbox user, in this case fred, which will go with fred@shawlw.me – there is no such user on the Internet so I beelive I am safe to use it as an example.

adduser fred
passwd fred
cd /home
ls -l
cd fred
mkdir Maildir
chown fred Maildir
chgrp fred Maildir
chmod 2775 Maildir

/etc/postfix/main.cf
We want to avoid double entries in our config files. doveconf -n | more (or dovecot -n) can let us chekc what is going on there, but systemctl restart postfix can show errors if double entires or bad entries.
Many Internet articles show entries that do not work.
Entries for /etc/postfix/main.cf… If we were using imap.shawlw.me it would be in the myhostname, and possibly /etc/hosts?
We don’t configure mynetworks values.
While the main.cf file shows alias_maps = hash:/etc/aliases, we don’t do anything with it.
Note that mailboxes will automatically be added by Dovecot once they are in use. Initially you may only see an inbox, but this is not to do with postfix.
Notice below the comodo certificates. Letsencrypt would use a different path and name, e.g. /etc/letsencrypt/live/shawlw.me/fullchain.pem, and privkey.pem.

myhostname = shawlw.me
mydomain = shawlw.me
myorigin = $mydomain
inet_interfaces = all
# inet_interfaces = localhost
inet_protocols = all
mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
home_mailbox = Maildir/
readme_directory = /usr/share/doc/postfix-2.10.1/README_FILES
smtp_tls_note_starttls_offer = yes
smtp_tls_security_level = may
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
relayhost = [email-smtp.us-west-2.amazonaws.com]:587
smtp_sasl_auth_enable = yes
smtp_use_tls = yes
smtpd_tls_key_file = /etc/pki/tls/private/shawlw_me.key
smtpd_tls_cert_file = /etc/pki/tls/certs/shawlw_me.crt
smtpd_tls_security_level = encrypt
smtpd_tls_loglevel = 2
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_local_domain =
smtpd_sasl_security_options = noanonymous
smtpd_sasl_auth_enable = yes
smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination
smtpd_tls_received_header = yes
smtpd_tls_session_cache_timeout = 3600s
smtpd_tls_auth_only=yes
smtp_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
smtpd_tls_CAfile = /etc/ssl/certs/ca-bundle.crt
smtp_sasl_mechanism_filter = plain, login
broken_sasl_auth_clients = yes
smtpd_sasl_authenticated_header = yes
smtp_sasl_type = cyrus
smtpd_use_tls = yes
smtp_sasl_path = private/auth
smtpd_sender_login_maps = hash:/etc/postfix/smtpd_sender_login_maps

Create the /etc/postfix/smtpd_sender_login_maps file that allows your username to be associated with the domain name:

vi smtpd_sender_login_maps
fred@shawlw.me fred
[save and exit the editor]
postmap hash:/etc/postfix/smtpd_sender_login_maps
chmod 0600 /etc/postfix/smtpd_sender_login_maps /etc/postfix/smtpd_sender_login_maps

If you add people to the maps file, change it to 777, do the same work, then back to 0600.
We assume postfix is already working from previous installation notes, so that you have the appropriate relayhost and have configured sasl_passwd correctly.

Configure the /etc/postfix/master.cf file… There may be double ups here to elsewhere, but that is ok.

cd /etc/postfix
vi master.cf
smtp      inet  n       -       n       -       -       smtpd

submission inet n       -       n       -       -       smtpd
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
  -o smtpd_sasl_type=dovecot
  -o smtpd_sasl_path=private/auth
  -o smtpd_sasl_security_options=noanonymous
  -o smtpd_sasl_local_domain=$myhostname
  -o smtpd_client_restrictions=permit_sasl_authenticated,reject
  -o smtpd_sender_restrictions=reject_sender_login_mismatch
  -o smtpd_recipient_restrictions=reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_sasl_authenticated,reject

smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
  -o smtpd_sasl_auth_enable=yes

[save and exit the editor]
</pre?

Create or edit existing files in /etc/pam.d - some entries may not be needed but certinaly dovecot and imap are...
cd /etc
vi emailuser
fred
fred@shawlw.me

[save and exit the editor - not sure if the second line is correct, but I have it.]

cd pam.d
vi dovecot
#%PAM-1.0
auth       required     pam_nologin.so
auth       include      password-auth
account    include      password-auth
session    include      password-auth
auth    required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail
account required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail

[save and exit]

vi imap
#%PAM-1.0
auth       required     pam_nologin.so
auth       include      password-auth
account    include      password-auth
session    include      password-auth
auth    required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail
account required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail

[save and exit]

vi smtp
#%PAM-1.0
auth       include	password-auth
account    include	password-auth
auth    required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail
account required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail

[save and exit]

vi smtpd
#%PAM-1.0
auth       include	password-auth
account    include	password-auth
auth    required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail
account required  pam_listfile.so  item=user sense=allow file=/etc/emailuser onerr=fail

[save and exit]

As said, my configs may have some non-required entries, which I have not had time as yet to test.

Edit /etc/dovecot/dovecot.conf… Again, these work, but other people can explain what they mean and if all of them are needed or not.

cd /etc/dovecot
vi dovecot.conf
protocols = imap pop3 lmtp
listen = *, ::

[save and exit - there are other files in ./conf.d that take care of other important configs]

cd /etc/dovecot/conf.d
vi 10-auth.conf
disable_plaintext_auth = no
auth_mechanisms = plain login

[save and exit - note, we are using the "no" option as we will be using SSL/TLS for plain text logins. "yes" will not authroise us.]

vi 10-ssl.conf
ssl = yes
ssl_cert = </etc/pki/tls/certs/shawlw_me.crt
ssl_key = </etc/pki/tls/private/shawlw_me.key

[save and exit - note, these are again comodo certificates. YOu would have yur own, or letsencrypt]


[Edit /etc/dovecot/conf.d/10-master.conf...]
vi 10-master.conf

service imap-login {
  inet_listener imap {
    port = 143
  }
  inet_listener imaps {
    port = 993
    ssl = yes
  }

service pop3-login {
  inet_listener pop3 {
    port = 110
  }
  inet_listener pop3s {
    port = 995
    ssl = yes
  }
}

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

[save and exit - as mentioned, we are not using pop3, but I can't spend time further on these configs now. These work. We may not even need toeh ports above except fot unix_listener. I have not tested.]

vi /etc/dovecot/conf.d/auth-system.conf.ext

passdb {
  driver = pam
  args = session=yes dovecot
  # args = %s
  # [session=yes] [setcred=yes] [failure_show_msg=yes] [max_requests=<n>]
  # [cache_key=<key>] [<service name>]
  #args = dovecot
}

[save and exit - you should notice userdb is already configured as well:
userdb {
  driver = passwd
}

So when you do doveconf -n -P you will see these entries

We now add sasl2 password for the user fred… again, this shows my own domain name. It will ask for the password for fred.

saslpasswd2 -c -u shawlw.me fred
sasldblistusers2

Other Settings

DNS MX record still uses 10 inbound-smtp.us-west-2.amazonaws.com (you would have your own e-mail zone in USA. e.g. Oregon or North Virginia)

SES default rule set for e-mail receiving:

I use the Lambda function for pre-checking an e-mail to meet dmarc/dkim (see my other installation notes) and then I put the e-mail into an S3 bucket. Only these basic steps as compared to my other setups that put S3 first, then dkim/dmarc and forwarding.

I installed S3FS (pseudo-NFS) and used this command to mount the S3 e-mail bucket that was held in Oregon: (I first made a directory called /var/s3email, and my SES default rules created the shawlw.me.xxx bucket and its permissions.

s3fs -o iam_role=”s3lws” -o use_path_request_style -o url=”https://s3-us-west-2.amazonaws.com” -o endpoint=us-west-2 -o dbglevel=info -o curldbg -o allow_other -o use_cache=”” shawlw.me.xxx /var/s3email

If this hangs, you have to open another shell, and kill -9 the s3fs process, unmount /var/s3eamil, and fix a corrupted directory with the linux command to fix the mount point, and try again. See my s3fs notes: (in this example:)
umount -f /var/s3email
fusermount -u /var/s3email
ls -l /var
df

When you try to remount, the df command will hang if there is an issue.

Then you run a crontab script every minute on this script, called email.sh

#!/bin/sh
cd /var/s3email
chmod 777 *
chown laurie *
mv * /home/laurie/Maildir/new
exit

(Use your own directory and user.)

crontab entry:

* * * * * /home/ec2-user/email.sh >/dev/null 2>&1

Some good websites with testing steps:
docs.gitlab.com/ee/administration/reply_by_email_postfix_setup.html

These need to work:
openssl s_client -starttls smtp -connect mail.example.com:25
openssl s_client -starttls smtp -connect shawlw.me:587
openssl s_client -starttls imap -connect mail.example.com:143

I’m going to do a more specific “from scratch” post for linux 2022.

When you add the site to Apple’s mail.app, manually add an account, in this case with the simple example settings of shawlw.me for in and outgoing email. It should realise yu are connecting with SSL for both. If it is, it should not take too long for the app to configure the account, and you can right click the new email in the app to get the account details to confirm SSL.

I’d rather not go into installing roundcubemail here as this is getting too long.
However, config.inc.php had these values:
$config[‘imap_host’] = ‘tls://shawlw.me:143’;
$config[‘smtp_host’] = ‘tls://shawlw.me’;

defaults.inc.php should not be used for modifications, rather config.inc.php, but here were my settings:
$config[‘imap_host’] = ‘localhost:143’;

Start typing and press Enter to search