Email quest

Written by Dominik Joe Pantůček on February 8, 2018.

As we have shown two weeks ago, email can be a very convenient tool for decent communication and in the future we will show that it can also be very secure tool if you need to send confidential information and verify its source using digital signature. But before we venture into that quadrant of space-time, we need to have a solid infrastructure in place. We start building such infrastructure with creating email server that can host virtual domains with multiple mailboxes and aliases. We will also ensure the mailboxes are accessible using common protocols and it is possible to easily administer the whole solution.

For our setup we use the postfix[1] as mail transfer agent, dovecot[2] as mail delivery agent and postfixadmin[3] – running on top of the Apache[4] web server – for administering the domains and accounts. In order to secure all TLS communication for all protocols, Let’s Encrypt[5] certificate authority client[6] is used.

Web server for administration interface

As we are a bunch of lazy sysadmins, we want to leverage web browser for any administration of the solution we design. We do not have any really specific needs, all we know is that any software we are about to install on the web server is written in PHP[7]. Therefore we use standard Apache HTTP server with PHP module installed. Installing on CentOS[8] is just a matter of:

yum install httpd php56
systemctl enable httpd
systemctl start httpd

We also want to use trusted TLS certificates from the start and so we install the shell implementation of Let’s Encrypt’s ACME protocol client,

git clone
cd ./
./ --install
. /root/

And we issue certificates for the domain name of our newly installed server. Also, after issuing the certificates, we change the SELinux[9] context if we are using SELinux in enforcing mode: --issue -d --apache   
chcon -t cert_t -R /root/

With newly issued certificates we configure TLS in Apache HTTP server by adding the following lines to appropriate HTTPS VirtualHost definition:

SSLCertificateFile /root/
SSLCertificateKeyFile /root/
SSLCertificateChainFile /root/

After all these changes, we just restart the Apache HTTP server:

systemctl restart httpd

And we are done with web server and TLS certificates.

Basic email configuration

Domains, mailboxes and aliases configuration will be stored in SQL[10] database in our solution. This is how combination of postfixadmin, postfix and your IMAP[11] server of choice works. We use MariaDB[12] – as there is no need for advanced database features. Just a bunch of tables with our data will suffice. Installation of MariaDB is as simple as:

yum install mariadb-server
systemctl enable mariadb
systemctl start mariadb

Now we are ready to install postfixadmin. The current version at the time of writing this article is 3.0.2 and before installation it is the most natural way to just unpack the distribution archive to the web server root directory:

tar -xzf postfixadmin-3.0.2.tar.gz -C /var/www/html
mv /var/www/html/postfixadmin-3.0.2 /var/www/html/postfixadmin

And before running the installation script, we create the database and database user for postfixadmin:

CREATE DATABASE postfixadmin;
GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixadmin'@'localhost' IDENTIFIED BY '********************';

Before installing postfixadmin, we need to fix access rights to the templates compilation directory:

cd /var/www/html/postfixadmin/
chown apache:apache templates_c
chcon -t httpd_sys_rw_content_t postfixadmin/templates_c/

Now we can configure the postfixadmin database access in /var/www/html/postfixadmin/ and then we can continue with its installation using the provided installation script by pointing our browser to an URL like

If everything went fine, we create our first super admin by issuing:

bash /var/www/html/postfixadmin/scripts/postfixadmin-cli admin add --password ******************** --password2 ******************** --superadmin 1 --active 1

At this moment we are able to configure domains, mailboxes and aliases. We are also able to create super administrators or domain administrators and let them do their work. Now on to actual mail delivery and reading.

Mail server

As mentioned earlier, we will use postfix mail server and our IMAP server of choice is dovecot. We install postfix with MariaDB/MySQL support from the “centosplus” repository:

yum --enablerepo=centosplus install postfix

Then we create required table lookup configuration files as mentioned in postfixadmin installation guide. We place them in /etc/postfix/sql directory. If we need more hardening the security of our solution, we also create separate SQL user for postfix, which has only read access to required tables. Remember, the postfixadmin user needs read and write access!

As we are creating solution for handling virtual domains and mailboxes, we use single system account for all mailboxes. It can be created by:

groupadd -g 5000 vmail
useradd -g vmail -u 5000 vmail -d /home/vmail -m

The constant id 5000 was chosen because it does not collide with any system identifiers or possible users created normally.

Now, in /etc/postfix/, we enable the SQL table lookups:

virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/
virtual_alias_maps = proxy:mysql:/etc/postfix/sql/, proxy:mysql:/etc/postfix/sql/, proxy:mysql:/etc/postfix/sql/
svirtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/, proxy:mysql:/etc/postfix/sql/

Now we only enable virtual_transport to go through dovecot service in the same configuration file and add TLS certificates:

smtpd_tls_cert_file = /root/
smtpd_tls_cert_file = /root/
smtpd_tls_key_file = /root/

After all these changes, we can start the postfix mail server:

systemctl enable postfix
systemctl start postfix

Installing dovecot IMAP server is pretty easy, just issue:

yum install dovecot dovecot-mysql

We enable the required protocols in main configuration file:

protocols = imap pop3 lmtp

Then we also configure the virtual mailboxes location on the filesystem:

mail_location = maildir:/home/vmail/%d/%n/Maildir
mail_privileged_group = mail
mail_uid = vmail
mail_gid = mail
first_valid_uid = 5000
last_valid_uid = 5000
first_valid_gid = 5000
last_valid_gid = 5000

We also need to configure MariaDB access using the same configuration we gave to postfix and then – once again – use the same TLS certificates:

ssl = yes
ssl_cert = 

Then we just fiddle with filesystem access rights and SELinux labels to ensure postfix and dovecot behave and start dovecot:

systemctl enable dovecot
systemctl start dovecot

And that is basically all. The overview of the solution we have just installed is depicted in picture 1 below.

Picture 1: overall schema of our newly installed mail server.


As we can see, this does not include all functionality we would like to see from our robust solution. Next week, we are about to finish this series by implementing all features mentioned in our previous email rant. See you next week!


1. The Postfix Home Page, Wietse Venema, available online at

2. Dovecot, Secure IMAP server, available online at

3. postfix.admin, Web based administration interface, available online at

4. Apache HTTP server project, available online at

5. Let's Encrypt, Free SSL/TLS Certificates, available online at

6., A pure Unix shell script implementing ACME client protocol, Neil Pang, available online at

7. PHP: Hypertext Preprocessor, available online at

8. CentOS Project, available online at

9. Security-Enhanced Linux. (2017, December 18). In Wikipedia, The Free Encyclopedia. Retrieved 22:49, January 20, 2018, from

10. SQL. (2018, January 19). In Wikipedia, The Free Encyclopedia. Retrieved 22:50, January 20, 2018, from

11. RFC 1730: INTERNET MESSAGE ACCESS PROTOCOL - VERSION 4, Network Working Group, December, 1994, available online at

12. MariaDB Foundation, official web available online at