0% found this document useful (0 votes)
57 views

Linux Postfix Configuration

This document provides instructions for setting up a secure mail server with Postfix, Dovecot and MariaDB on CentOS 7. It includes steps to install required packages, set up the MariaDB database to store user and domain information, add data to the database tables, and configure Postfix and Dovecot to use the MariaDB database for authentication and mailbox delivery.

Uploaded by

HamzaKhan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
57 views

Linux Postfix Configuration

This document provides instructions for setting up a secure mail server with Postfix, Dovecot and MariaDB on CentOS 7. It includes steps to install required packages, set up the MariaDB database to store user and domain information, add data to the database tables, and configure Postfix and Dovecot to use the MariaDB database for authentication and mailbox delivery.

Uploaded by

HamzaKhan
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 14

Email with Postfix, Dovecot and MariaDB on

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.

Install Required PackagesPermalink


1. Install any outstanding package updates:
yum update

2. Install the required packages:


yum install postfix dovecot mariadb-server dovecot-mysql

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.

Creating the Database and TablesPermalink


Follow the steps below to create the database tables for virtual users, domains and aliases:
1. Ensure the MariaDb server is running and enabled to start automatically on reboot:
sudo systemctl start mariadb
sudo systemctl enable mariadb

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

Answer Y at the following prompts:


• Remove anonymous users?
• Disallow root login remotely?
• Remove test database and access to it?
• Reload privilege tables now?
3. Create a new database:
sudo mysqladmin -u root -p create mailserver

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';

6. Flush the MySQL privileges to apply the change:


FLUSH PRIVILEGES;

7. Switch to the new mailsever database:


USE mailserver;

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;

9. Create a table for all of the email addresses and passwords:


CREATE TABLE `virtual_users` (
`id` int(11) NOT NULL auto_increment,
`domain_id` int(11) NOT NULL,
`password` varchar(106) NOT NULL,
`email` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

10.Create a table for the email aliases:


CREATE TABLE `virtual_aliases` (
`id` int(11) NOT NULL auto_increment,
`domain_id` int(11) NOT NULL,
`source` varchar(100) NOT NULL,
`destination` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
FOREIGN KEY (domain_id) REFERENCES virtual_domains(id) ON DELETE CASCADE
) 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

2. Check the contents of the virtual_domains table:


SELECT * FROM mailserver.virtual_domains;

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)

6. Check the virtual_aliases table:


SELECT * FROM mailserver.virtual_aliases;

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)

8. If all the desired data displays as expected, exit MySQL:


exit

1. mailbox_maps, virtual_alias_maps, and mysql-virtual-email2email files.


These files contain the connection information for the MySQL lookup tables created in the
MariaDB section of this guide. Postfix will use this data to identify all domains, corresponding
mailboxes, and valid users.
Create the file for virtual_mailbox_domains. Replace the value for password with
your database user’s password. This password was created in the Creating the Database and
Tables section. If you used a different name for your database user and dbname replace those
with your own values:
/etc/postfix/mysql-virtual-mailbox-domains.cf
1 user = mailuser
2 password = mailuserpass
3 hosts = 127.0.0.1
4 dbname = mailserver
5 query = SELECT 1 FROM virtual_domains WHERE name='%s'

2. Create the /etc/postfix/mysql-virtual-mailbox-maps.cf file, and enter the


following values. Use the database user’s password and make any other changes as needed:
/etc/postfix/mysql-virtual-mailbox-maps.cf
1 user = mailuser
2 password = mailuserpass
3 hosts = 127.0.0.1
4 dbname = mailserver
5 query = SELECT 1 FROM virtual_users WHERE email='%s'

3. Create the /etc/postfix/mysql-virtual-alias-maps.cf file and enter the


following values. Use the database user’s password and make any other changes as needed:
/etc/postfix/mysql-virtual-alias-maps.cf
1 user = mailuser
2 password = mailuserpass
3 hosts = 127.0.0.1
4 dbname = mailserver
5 query = SELECT destination FROM virtual_aliases WHERE source='%s'

4. Create the /etc/postfix/mysql-virtual-email2email.cf file and enter the


following values. Use the database user’s password and make any other changes as needed:
/etc/postfix/mysql-virtual-email2email.cf
1 user = mailuser
2 password = mailuserpass
3 hosts = 127.0.0.1
4 dbname = mailserver
5 query = SELECT email FROM virtual_users WHERE email='%s'

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

Master Program SettingsPermalink


Postfix’s master program starts and monitors all of Postfix’s processes. The configuration file
master.cf lists all programs and information on how they should be started.

1. Make a copy of the /etc/postfix/master.cf file:


sudo cp /etc/postfix/master.cf /etc/postfix/master.cf.orig

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

2. Edit the /etc/dovecot/dovecot.conf file. Uncomment protocols = imap pop3


lmtp in the # Protocols we want to be serving. section of the file:

/etc/dovecot/dovecot.conf
1 ## Dovecot configuration file
2 ...
3 # Protocols we want to be serving.
4 protocols = imap pop3 lmtp

3. Edit the /etc/dovecot/conf.d/10-mail.conf file. This file controls how Dovecot


interacts with the server’s file system to store and retrieve messages.
Modify the following variables within the configuration file:
/etc/dovecot/conf.d/10-mail.conf
1 ...
2 mail_location = maildir:/var/mail/vhosts/%d/%n
3 ...
4 mail_privileged_group = mail
5 ...

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/

7. Edit the user authentication file, located in /etc/dovecot/conf.d/10-auth.conf.


Uncomment the following variables and replace with the file excerpt’s example values:
/etc/dovecot/conf.d/10-auth.conf
1 ...
2 disable_plaintext_auth = yes
3 ...
4 auth_mechanisms = plain login
5 ...
6 !include auth-system.conf.ext
7 ...
8 !include auth-sql.conf.ext
9 ...

8. Edit the /etc/dovecot/conf.d/auth-sql.conf.ext file with authentication and


storage information. Ensure your file contains the following lines and that they are
uncommented:
/etc/dovecot/conf.d/auth-sql.conf.ext
1 ...
2 passdb {
3 driver = sql
4 args = /etc/dovecot/dovecot-sql.conf.ext
5 }
6 ...
7 userdb {
8 driver = static
9 args = uid=vmail gid=vmail home=/var/mail/vhosts/%d/%n
10 }
11 ...

9. Create the /etc/dovecot/dovecot-sql.conf.ext file and update it with your


MySQL connection information. Add the following variables and replace the values with the
excerpt example. Replace dbname, user and password with your own MySQL database
values:
/etc/dovecot/dovecot-sql.conf.ext
1 driver = mysql
2 connect = host=127.0.0.1 dbname=mailserver user=mailuser password=mailuserpass
3 default_pass_scheme = SHA512-CRYPT
4 password_query = SELECT email as user, password FROM virtual_users WHERE email='

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

12.Edit the service settings file /etc/dovecot/conf.d/10-master.conf:

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 }

Locate service auth and configure it as shown below:

/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 }

Save the changes to the /etc/dovecot/conf.d/10-master.conf file.

13.Edit /etc/dovecot/conf.d/10-ssl.conf file to require SSL and to add the location


of your domain’s SSL certificate and key. Replace example.com with your domain:

/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

14.Restart Dovecot to enable all configurations:


sudo systemctl restart dovecot

Test Your ConfigurationPermalink


Note
Given the possibility of hosting a large number of virtual domains on a single mail system,
the username portion of an email address (i.e. before the @ sign) is not sufficient to
authenticate to the mail server. When email users authenticate to the server, they must
supply their email clients with the entire email address created above as their username.

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

4. You should see output similar to the following:


.
./dovecot-uidvalidity
./new
./maildirfolder
./dovecot.index.cache
./cur
./cur/1539202420.M440788P27259.mail,S=450,W=465:2,S
./dovecot.index.log
./dovecot-uidlist
./dovecot-uidvalidity.5bbe5d50
./tmp

For a different Linux distribution or different mail server, review our email tutorials.

Note About Email at Linode


This guide may involve or result in sending email. In an effort to fight spam, Linode
restricts outbound connections on ports 25, 465, and 587 on all Linodes for new accounts
created after November 5th, 2019. For more information, please see Sending Email on
Linode.

Before You BeginPermalink


1. Set up the Linode as specified in the Getting Started and Securing Your Server guides.
2. Verify that the iptables firewall is not blocking any of the standard mail ports (25, 465, 587,
110, 995, 143, and 993). If using a different form of firewall, confirm that it is not blocking
any of the needed ports.
3. Review the concepts in the Running a Mail Server guide.

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.

Update Hosts FilePermalink


Verify that the hosts file contains a line for the Linode’s public IP address and is associated with the
Fully Qualified Domain Name (FQDN). In the example below, 192.0.2.0 is the public IP address,
hostname is the local hostname, and hostname.example.com is the FQDN.

/etc/hosts
1 127.0.0.1 localhost.localdomain localhost
2 192.0.2.0 hostname.example.com hostname

You might also like