Postfix Configuration

INCOMPLETE I am still updating the documentation related to mail packages. Your patience is appreciated.

The needs of an SMTP server can vary quite extensively, it would be very difficult to attempt to cover all of them here.

There are several use case cases that are covered here. Your individual needs may differ, but hopefully this gets you started.

The use cases specifically covered:

Postfix Null Client MTA
This is a Postfix server that sends e-mail on behalf of applications running on the server (such as WordPress blog notifications) but does not accept any external connections. It only acts as a client when connecting with other MTA servers on the Internet.
Configuration instructions are detailed on the Postfix Null Client MTA page.
Postfix MX MTA Server
This is a Postfix server that accepts e-mail on behalf of a mailbox domain. It always listens on Port 25 and unfortunately to be RFC compliant, it must accept connections that are not encrypted. Encrypted connections however are not only allowed, but highly encouraged.
Configuration instructions are detailed on the Postfix MX MTA Server page.
Postfix Submission MTA
This is a Postfix server that accepts authenticated connections from e-mail Clients. Historically it listened for connections on TCP Port 587. As of RFC 8314 (January 2018) it should listen on TCP Port 465 and only accept encrypted connections using TLS 1.2 or better.
Configuration instructions are detailed on the Postfix Submission MTA page.
Postfix Backup MX Server
This is an MX server that accepts e-mail for your mailbox domain in the event an MTA with a message to deliver is not able to connect to your primary MX server. It should be located at a physically different data center than your primary MX server is hosted at.
Configuration instructions have not yet been written.

Postfix Common Configuration Topics

Regardless of your use case, some things are the same.

Local Caching Resolver

From MX records to A/AAAA records to TXT records (for SPF policy and DKIM signatures) to TLSA records, mail servers rely heavily upon DNS results. Modified DNS results can seriously compromise the security of messages relayed through your server.

Do not run a mail server unless you also are running a DNSSEC enforcing local resolver on the same host. Just don’t. Technically it is optional but there is not a sane reason not to.

Before proceeding with anything else, follow the instruction on the Unbound DNS Resolver page.

The /etc/aliases File

When there is a problem on the server, including mail a delivery problem, notice of the problem needs to get to a real person. This is normally achieved by sending a message to a standardized user name which is an alias to another standardized user name that itself is often also an alias. By default on CentOS 7 systems, all aliases ultimately lead to the message being delivered to the root user. This is not ideal.

You should create at least one more alias, so that mail sent to the root user ends up being delivered to an account used by a system administrator. The file that determines the alias delivery path is the /etc/aliases file.

This is a flat file database with key: value pairs to be used for directing mail delivery on the system itself. Each key indicates that mail username is an alias for value with respect to the mail system. For example, from that file:

# Basic system aliases -- these MUST be present.
mailer-daemon:	postmaster
postmaster:	root

Mail sent to the username mailer-daemon gets redirected to the username postmaster. Similarly, mail sent to the username postmaster gets redirected to the username root.

You should add an alias to specify who should get mail sent to the root user. If your non-root username on the system is alice then edit /etc/aliases so that the end of the file looks like this:

# trap decode to catch security attacks
decode:		root

# Person who should get root's mail
root:		alice

Once making that change, you must run the command newaliases:

[root@host ~]# newaliases

Now any mail that would ultimately end up in the root inbox instead will end up in the inbox for alice.

The ~/.forward File

When there is new mail you will get notice that there is new mail for the user alice whenever you log in as alice but it is much more efficient to have that mail forwarded to an e-mail account you regularly check.

To get the system to forward e-mail sent to alice to your actual e-mail address, create the file
/home/alice/.forward (note the .) containing the following:

username@wherever.net

Obviously replace username@wherever.net with your actual e-mail address. This way e-mail sent to the root user which is an alias to alice gets forwarded to username@wherever.net and Postfix will send it to your preferred e-mail account.

You can test that this is working with the following command:

[user@host ~]$ echo "test aliases" |mail -s "Hello" root

If you got it, the aliases are working right and the ~/.forward file is working right. If you did not get it, check your spam filter and check /var/log/maillog. It is important this works. When initially setting up a new server is when it is most likely to be rejected as spam by the MX server associated with the e-mail address you used in ~/.forward or delivered to you but filtered as junk.

If you get an error that the mail command does not exist, install the mailx package. It is not always installed automatically when installing RHEL/CentOS.

Reverse DNS

When Postfix connects to another MTA it will send a hostname as part of the greeting. The receiving MTA will compare that hostname with a Reverse DNS lookup and if they do not match, the message is far more likely to be flagged as spam or possibly even rejected.

While there is no limit to the number of domain names that can resolve to an IP address, an IP address will only have one domain name that a Reverse DNS lookup will resolve to.

The domain name really needs to be one in a DNS zone you control so that you can obtain a Certificate Authority signed x.509 certificate for it if needed.

For a web server where I will be running a Null Client MTA I generally use the domain name of the first server I set up for it. For a mail server that will have the primary MX server, IMAP server, and Submission MTA server on the same host I usually use mail. followed by the mailbox domain (e.g. mail.example.org).

First, make sure both both A and AAAA records exist for the chosen domain name, and that they point to the respective IPv4 and IPv6 addresses for the host.

Next, you will have to get your hosting facility to assign that domain name as the Reverse IP for both the IPv4 and IPv6 address of the host. Most hosting facilities have an interface in their control panel that lets you do that without needing a support request. For example:

[Reverse DNS Panel at Linode]
Reverse DNS Panel at Linode

It sometimes takes several hours for the change to take effect. Make sure to set the Reverse DNS for both your IPv4 and IPv6 address.

Finally, it is a good idea to set your system name to that name as well:

[root@host ~]# hostnamectl set-hostname mail.example.net

Obviously replace mail.example.net with the hostname you used for Reverse DNS.

Backup Existing Configuration

Unless this is a brand new install, backup your existing Postfix configuration files in case you need to refer to them:

[root@host ~]# cd /etc/postfix
[root@host postfix]# cp main.cf backup-main-20190223.cf
[root@host postfix]# cp master.cf backup-master-20190223.cf
[root@host postfix]# postconf > old-postconf-output-20190223.txt

Update Postfix Version

The Postfix in LibreLAMP is a much newer version than what RHEL/CentOS 7.6 ships with. Update it and replace the former configuration files with the new defaults. Since the Postfix that LibreLAMP ships with is a major update by several versions to what RHEL/CentOS 7 ships with, make sure to start with the fresh default configuration as some syntax has changed.

[root@host ~]# systemctl stop postfix.service
[root@host ~]# yum -y update postfix
[root@host ~]# cd /etc/postfix
[root@host postfix]# [ -f main.cf.rpmnew ] && cat main.cf.rpmnew > main.cf
[root@host postfix]# [ -f master.cf.rpmnew ] && cat master.cf.rpmnew > master.cf
[root@host postfix]# systemctl enable postfix.service
[root@host postfix]# systemctl start postfix.service

Internet Host and Domain Names

There are two parameters related to domain names that need to be set up correctly: myhostname and mydomain.

If you followed the instructions for Reverse DNS including the hostnamectl command, there is a good chance everything is as it should be, but you still need to verify.

myhostname

To see what this currently resolves to within Postfix:

[user@host ~]$ postconf |grep "^myhostname"

From the Postfix documentation:

The myhostname parameter specifies the internet hostname of this mail system. The default is to use the fully-qualified domain name from gethostname(). $myhostname is used as a default value for many other configuration parameters.

The myhostname parameter needs to be set to the domain name used for Reverse DNS. For example, if you have configured Reverse DNS for your IP address to mail.example.net then the above command should have returned myhostname = mail.example.net.

If it does not, you can explicitly set it:

[root@host ~]# postconf -e "myhostname = mail.example.net"
[root@host ~]# postfix reload

mydomain

From the Postfix documentation:

The mydomain parameter specifies the local internet domain name. The default is to use $myhostname minus the first component. $mydomain is used as a default value for many other configuration parameters.

This generally is correct, but you can check what the value is by using the command:

[user@host ~]$ postconf |grep "^mydomain ="

It should return your domain as it is registered with your domain registrar. If it does not, run postfix reload just to make sure other changes are reflected and run the check again. If it still does not, you can explicitly set it:

[root@host ~]# postconf -e "mydomain = example.net"
[root@host ~]# postfix reload

DNSSEC Related Tweaks

There are two setting in the LibreLAMP default configuration that can not be set to their optimal value unless the local host has a DNSSEC enforcing recursive resolver installed and running.

If you followed the Unbound install instructions, you should make these changes to the Postfix configuration now:

[root@host ~]# postconf -e "smtp_dns_support_level = dnssec"
[root@host ~]# postconf -e "smtp_tls_security_level = dane"
[root@host ~]# postfix reload

Those changes will increase the security of outgoing message to MX servers that implement RFC 7672.

blah delete


Postfix Basic Configuration

The standard port for an SMTP server is TCP port 25. This section will help you get Postfix running on that port.

However it is imperative that you also set up the TLS instructions in the section that follows. Not just for the security reasons, but for availability. Many SMTP servers running on Port 25 are spam relays, and for this reason many Internet Service Providers block access to Port 25. The solution is to use the submission Port 587 for sending e-mail from an e-mail client, and that requires TLS.

The file we need to configure for basic mail services is /etc/postfix/main.cf. It is always good to make a time-stamped backup of that file whenever making edits:

cd /etc/postfix
cp -p main.cf main.cf-20190223.bak

Now it is safe to edit the file.

Misc Settings

By default, Postfix is only listening on the localhost. That is how it should behave when its only job is to send messages between users on the same host. To run it as a mail server we can connect to from the outside world, we need to change the inet_interfaces setting. Comment out the line that reads:

inet_interfaces = localhost

Then add the following line:

inet_interfaces = all

By default, Postfix will only accept e-mail destined for the host defined earlier with the $myhostname definition and for the localhost. Usually (and in our example scenario) $myhostname and $mydomain differ. We need it to accept e-mail for $mydomain as well. Assuming they are actually different on your setup, comment out the line that reads:

mydestination = $myhostname, localhost.$mydomain, localhost

After the comment block it appears in, add the following line:

mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain

No one likes an open relay. Well, okay, spammers like an open relay, but no one else does.

At least initially, you should make sure that Postfix only ‘trusts’ the local machine to relay mail. Find the line that reads:

#mynetworks_style = host

Un-comment it so that it now reads:

mynetworks_style = host

That will allow scripts on the local machine to send mail when they need to without needing to authenticate, while at the same time still keeping the mail server closed to outside users who have not authenticated themselves.

Note that if you plan to use the server as a mail relay for applications running on another machine, you will probably need to manually specify a list of hosts that are allowed to relay mail. See the Postfix documentation for more information.