Linux Postfix Configuration
Linux Postfix Configuration
CentOS 7
In this guide, you’ll learn how to set up a secure virtual user mail server with
Postfix, Dovecot, and MariaDB (a drop-in replacement for MySQL) on CentOS 7. We’ll
explain how to create new user mailboxes and send or receive email to and from
configured domains.
Which names would you like to activate HTTPS for?
-----------------------------------------------------------------------------
--
1: example.com
2: www.example.com
-----------------------------------------------------------------------------
--
Select the appropriate numbers separated by commas and/or spaces, or leave
input
blank to select all options shown (Enter 'c' to cancel):
1. Certbot will also ask if you would like to automatically redirect HTTP traffic to HTTPS traffic.
It is recommended that you select this option.
2. When the tool completes, Certbot will store all generated keys and issued certificates in the
/etc/letsencrypt/live/$domain directory, where $domain is the name of the
domain entered during the Certbot certificate generation step.
Note
Certbot recommends pointing your web server configuration to the default
certificates directory or creating symlinks. Keys and certificates should not be
moved to a different directory.
Finally, Certbot will update your web server configuration so that it uses the new certificate, and
also redirects HTTP traffic to HTTPS if you chose that option.
3. If you have a firewall configured on your Linode, you can add a firewall rule to allow incoming
and outgoing connections to the HTTPS service. On CentOS, firewalld is the default tool for
managing firewall rules. Configure firewalld for HTTP and HTTPS traffic:
sudo firewall-cmd --zone=public --permanent --add-service=http
sudo firewall-cmd --zone=public --permanent --add-service=https
sudo firewall-cmd --reload
Make a note of the certificate and key locations on the Linode. You will need the path to each during
the Dovecot configuration steps.
This installs the Postfix mail server, the MariaDB database server, the Dovecot IMAP and POP
daemons, and several supporting packages that provide services related to authentication.
VersionsPermalink
This guide uses the following package versions:
• Postfix 2.10.1
• Dovecot 2.2.10
• MariaDB 5.5.60
MariaDBPermalink
In this section you will set up a MariaDB database to store virtual domains, users and passwords.
Dovecot and Postfix require this data.
2. Use the mysql_secure_installation tool to configure additional security options. This tool will
ask if you want to set a new password for the MySQL root user, but you can skip that step:
sudo mysql_secure_installation
4. Log in to MySQL:
sudo mysql -u root -p
5. Create the MySQL user and grant the new user permissions over the database. Replace
mailuserpass with a secure password:
GRANT SELECT ON mailserver.* TO 'mailuser'@'127.0.0.1' IDENTIFIED BY
'mailuserpass';
8. Create a table for the domains that will receive mail on the Linode:
CREATE TABLE `virtual_domains` (
`id` int(11) NOT NULL auto_increment,
`name` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Adding DataPermalink
You can now add data to the database and tables that were created in the previous section.
1. Add the domains to the virtual_domains table. Replace the values for example.com
and hostname with your own settings:
INSERT INTO `mailserver`.`virtual_domains`
(`id` ,`name`)
VALUES
('1', 'example.com'),
('2', 'hostname.example.com'),
('3', 'hostname'),
('4', 'localhost.example.com');
Note
Note which id corresponds to which domain, the id value is necessary for the next
two steps.
2. Add email addresses to the virtual_users table. The domain_id value references the
virtual_domain table’s id value. Replace the email address values with the addresses that
you wish to configure on the mailserver. Replace the password values with strong passwords.
INSERT INTO `mailserver`.`virtual_users`
(`id`, `domain_id`, `password` , `email`)
VALUES
('1', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))),
'email1@example.com'),
('2', '1', ENCRYPT('password', CONCAT('$6$', SUBSTRING(SHA(RAND()), -16))),
'email2@example.com');
3. An email alias will forward all email from one email address to another. To set up an email
alias, add it to the virtual_aliases table:
INSERT INTO `mailserver`.`virtual_aliases`
(`id`, `domain_id`, `source`, `destination`)
VALUES
('1', '1', 'alias@example.com', 'email1@example.com');
TestingPermalink
In the previous section, data was added to the MySQL mailserver database. The steps below will
test that the data has been stored and can be retrieved.
1. Log in to MySQL:
sudo mysql -u root -p
3. Verify that the output displays the domains you add to the virtual_domains table:
+----+-----------------------+
| id | name |
+----+-----------------------+
| 1 | example.com |
| 2 | hostname.example.com |
| 3 | hostname |
| 4 | localhost.example.com |
+----+-----------------------+
4 rows in set (0.00 sec)
4. Check the virtual_users table:
SELECT * FROM mailserver.virtual_users;
5. Verify that the output displays the email addresses you added to the virutal_users table.
Your hashed passwords will appear longer than they are displayed below:
+----+-----------+-------------------------------------+--------------------+
| id | domain_id | password | email |
+----+-----------+-------------------------------------+--------------------+
| 1 | 1 | $6$574ef443973a5529c20616ab7c6828f7 | email1@example.com |
| 2 | 1 | $6$030fa94bcfc6554023a9aad90a8c9ca1 | email2@example.com |
+----+-----------+-------------------------------------+--------------------+
2 rows in set (0.01 sec)
7. Verify that the output displays the aliases you added to the virtual_aliases table:
+----+-----------+-------------------+--------------------+
| id | domain_id | source | destination |
+----+-----------+-------------------+--------------------+
| 1 | 1 | alias@example.com | email1@example.com |
+----+-----------+-------------------+--------------------+
1 row in set (0.00 sec)
5. Restart Postfix:
sudo systemctl restart postfix
6. The postmap command creates or queries Postfix’s lookup tables, or updates an existing one.
Enter the following command to ensure that Postfix can query the virtual_domains table.
Replace example.com with the first name value. The command should return 1 if it is
successful:
sudo postmap -q example.com mysql:/etc/postfix/mysql-virtual-mailbox-
domains.cf
7. Test Postfix to verify that it can retrieve the first email address from the MySQL table
virtual_users. Replace email1@example.com with the first email address added to
the table. You should receive 1 as the output:
sudo postmap -q email1@example.com mysql:/etc/postfix/mysql-virtual-mailbox-
maps.cf
Verify that Postfix can retrieve the first email address from the MySQL table
virtual_users using the database values entered in the mysql-virtual-mailbox-
maps.cf file. Replace email1@example.com with the first email address added to the
table. You should receive 1 as the output:
sudo postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-
email2email.cf
8. Test Postfix to verify that it can query the virtual_aliases table. Replace
alias@example.com with the first source value created in the table. The command
should return the destination value for the row:
sudo postmap -q alias@example.com mysql:/etc/postfix/mysql-virtual-alias-
maps.cf
2. Edit /etc/postfix/master.cf to contain the values in the excerpt example. The rest of
the file can remain unchanged:
/etc/postfix/master.cf
1 #
2 # Postfix master process configuration file. For details on the format
3 # of the file, see the master(5) manual page (command: "man 5 master" or
4 # on-line: http://www.postfix.org/master.5.html).
5 #
6 # Do not forget to execute "postfix reload" after editing this file.
7 #
8 # ==========================================================================
9 # service type private unpriv chroot wakeup maxproc command + args
10 # (yes) (yes) (yes) (never) (100)
11 # ==========================================================================
12 smtp inet n - n - - smtpd
13 #smtp inet n - - - 1 postscreen
14 #smtpd pass - - - - - smtpd
15 #dnsblog unix - - - - 0 dnsblog
16 #tlsproxy unix - - - - 0 tlsproxy
17 submission inet n - - - - smtpd
18 -o syslog_name=postfix/submission
19 -o smtpd_tls_security_level=encrypt
20 -o smtpd_sasl_auth_enable=yes
21 -o smtpd_sasl_type=dovecot
22 -o smtpd_sasl_path=private/auth
23 -o smtpd_reject_unlisted_recipient=no
24 -o smtpd_client_restrictions=permit_sasl_authenticated,reject
25 -o milter_macro_daemon_name=ORIGINATING
26 smtps inet n - - - - smtpd
27 -o syslog_name=postfix/smtps
28 -o smtpd_tls_wrappermode=yes
29 -o smtpd_sasl_auth_enable=yes
30 -o smtpd_sasl_type=dovecot
31 -o smtpd_sasl_path=private/auth
32 -o smtpd_client_restrictions=permit_sasl_authenticated,reject
33 -o milter_macro_daemon_name=ORIGINATING
34 ...
3. Change the permissions of the /etc/postfix directory to restrict permissions to allow only
its owner and the corresponding group:
sudo chmod -R o-rwx /etc/postfix
4. Restart Postfix:
sudo systemctl restart postfix
DovecotPermalink
Dovecot is the Mail Delivery Agent (MDA) which is passed messages from Postfix and delivers them
to a virtual mailbox. In this section, configure Dovecot to force users to use SSL when they connect so
that their passwords are never sent to the server in plain text.
1. Copy all of the configuration files so you can easily revert back to them if needed:
sudo cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.orig
sudo cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10-
mail.conf.orig
sudo cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10-
auth.conf.orig
sudo cp /etc/dovecot/conf.d/auth-sql.conf.ext /etc/dovecot/conf.d/auth-
sql.conf.ext.orig
sudo cp /etc/dovecot/conf.d/10-master.conf /etc/dovecot/conf.d/10-
master.conf.orig
sudo cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.orig
/etc/dovecot/dovecot.conf
1 ## Dovecot configuration file
2 ...
3 # Protocols we want to be serving.
4 protocols = imap pop3 lmtp
4. Create the /var/mail/vhosts/ directory and a subdirectory for your domain. Replace
example.com with your domain name:
sudo mkdir -p /var/mail/vhosts/example.com
This directory will serve as storage for mail sent to your domain.
5. Create the vmail group with ID 5000. Add a new user vmail to the vmail group. This
system user will read mail from the server.
sudo groupadd -g 5000 vmail
sudo useradd -g vmail -u 5000 vmail -d /var/mail/
6. Change the owner of the /var/mail/ folder and its contents to belong to vmail:
sudo chown -R vmail:vmail /var/mail/
The password_query variable uses email addresses listed in the virtual_users table as
the username credential for an email account.
To use an alias as the username:
1. Add the alias as the source and destination email address to the
virtual_aliases table.
2. Change the /etc/dovecot/dovecot-sql.conf.ext file’s password_query
value to password_query = SELECT email as user, password FROM
virtual_users WHERE email=(SELECT destination FROM
virtual_aliases WHERE source = '%u');
10.Change the owner and group of the /etc/dovecot/ directory to vmail and dovecot:
sudo chown -R vmail:dovecot /etc/dovecot
11.Change the permissions on the /etc/dovecot/ directory to be recursively read, write, and
execute for the owner of the directory:
sudo chmod -R o-rwx /etc/dovecot
Note
When editing the file, be careful not to remove any opening or closing curly braces.
If there’s a syntax error, Dovecot will crash silently. You can check
/var/log/upstart/dovecot.log to debug the error.
Disable unencrypted IMAP and POP3 by setting the protocols’ ports to 0. Uncomment the
port and ssl variables:
/etc/dovecot/conf.d/10-master.conf
1 ...
2 service imap-login {
3 inet_listener imap {
4 port = 0
5 }
6 inet_listener imaps {
7 port = 993
8 ssl = yes
9 }
10 ...
11 }
12 ...
13 service pop3-login {
14 inet_listener pop3 {
15 port = 0
16 }
17 inet_listener pop3s {
18 port = 995
19 ssl = yes
20 }
21 }
22 ...
Find the service lmtp section of the file and use the configuration shown below:
/etc/dovecot/conf.d/10-master.conf
1 ...
2 service lmtp {
3 unix_listener /var/spool/postfix/private/dovecot-lmtp {
4 #mode = 0666i
5 mode = 0600
6 user = postfix
7 group = postfix
8 }
9 ...
10 }
/etc/dovecot/conf.d/10-master.conf
1 ...
2 service auth {
3 ...
4 unix_listener /var/spool/postfix/private/auth {
5 mode = 0660
6 user = postfix
7 group = postfix
8 }
9
10 unix_listener auth-userdb {
11 mode = 0600
12 user = vmail
13 }
14 ...
15 user = dovecot
16 }
17 ...
In the service auth-worker section, uncomment the user line and set it to vmail:
/etc/dovecot/conf.d/10-master.conf
1 ...
2 service auth-worker {
3 ...
4 user = vmail
5 }
/etc/dovecot/conf.d/10-ssl.conf
1 ...
2 # SSL/TLS support: yes, no, required. <doc/wiki/SSL.txt>
3 ssl = required
4 ...
5 ssl_cert = </etc/letsencrypt/live/example.com/fullchain.pem
6 ssl_key = </etc/letsencrypt/live/example.com/privkey.pem
1. Prior to accessing any newly-created email account, a test message needs to be sent to create
that user’s mailbox (replace email1@example.com with an address that you have
configured in your database):
yum install mailx
mail email1@example.com
Enter a subject and message (optional), then press Ctrl+D to complete and send the message.
2. After the test mail is sent, check /var/log/maillog to make sure the mail was delivered.
tail /var/log/maillog
At the end of the file, you should see something similar to the following:
/var/log/maillog
1 Mar 18 17:18:47 localhost postfix/cleanup[3427]: B624062FA: message-id=<20150318
2 Mar 18 17:18:47 localhost postfix/qmgr[3410]: B624062FA: from=<root@example.com>
3 Mar 18 17:18:47 localhost postfix/pipe[3435]: B624062FA: to=<email1@example.com>
4 Mar 18 17:18:47 localhost postfix/qmgr[3410]: B624062FA: removed
3. Now you can test to see what the users of your email server would see with their email clients.
To test the email1@example.com mailbox, navigate to the mailbox directory
/var/mail/vhosts/example.com/email1 and issue the following command:
find
For a different Linux distribution or different mail server, review our email tutorials.
Configure DNSPermalink
When you’re ready to update the DNS and start sending mail to the server, edit the domain’s MX
record so that it points to the Linode’s domain or IP address, similar to the example below:
example.com A 10 12.34.56.78
example.com MX 10 example.com
mail.example.com MX 10 example.com
Make sure that the MX record is changed for all domains and subdomains that might receive email. If
setting up a brand new domain, these steps can be performed prior to configuring the mail server. When
using Linode’s DNS Manager, create an MX record that points to the desired domain or subdomain,
and then create an A record for that domain or subdomain, which points to the correct IP address.
/etc/hosts
1 127.0.0.1 localhost.localdomain localhost
2 192.0.2.0 hostname.example.com hostname