X

Set up a mail server with PostfixAdmin and MariaDB on CentOS 7

In this guide, we will explain how to setup and configure a mail server with PostfixAdmin, Postfix, Dovecot, MariaDB and SpamAssasin on a CentOS VPS. PostfixAdmin is a PHP-based web front-end that allows you to manage virtual domains and users for a Postfix mail transport agent. This guide should work on other Linux VPS systems as well but was tested and written for a CentOS 7 VPS.

If you use an Ubuntu VPS, follow our tutorial to set up a mail server with Postfix, Dovecot, Spamassassin, SQLite and PostfixAdmin on an Ubuntu 16.04 VPS

If you want to use SQLite instead of MariaDB, follow our tutorial to set up a mail server with Postfix, Dovecot, Spamassassin, SQLite and PostfixAdmin on a CentoOS 7 VPS

1. Update the system and install necessary packages

yum update && yum install wget nano

2. Create system user

For security reasons, we will create a new system user who will be the owner of all mailboxes.

useradd -r -u 150 -g mail -d /var/vmail -s /sbin/nologin -c "Virtual Mail User" vmail
mkdir -p /var/vmail
chmod -R 770 /var/vmail
chown -R vmail:mail /var/vmail

3. Install MariaDB

MariaDB 5.5 is shipped in the default CentOS 7 repository, to install it just run:

yum install mariadb-server

To start the MariaDB service and enable it to start on boot, execute the following commands:

systemctl start mariadb.service
systemctl enable mariadb.service

Run the following command to secure your MariaDB installation:

mysql_secure_installation

Next, we need to create a database for our postfixadminHQ instance.

mysql -uroot -p
MariaDB [(none)]> CREATE DATABASE postfixadmin;
MariaDB [(none)]> GRANT ALL PRIVILEGES ON postfixadmin.* TO 'postfixadmin'@'localhost' IDENTIFIED BY 'strong_password';
MariaDB [(none)]> FLUSH PRIVILEGES;
MariaDB [(none)]> \q

4. Install PHP and all necessary PHP modules

CentOS 7 ships with PHP version 5.4, to install PHP and necessary modules, run:

yum install php php-mysql php-imap php-mbstring php-common

If you don’t have Apache installed, install it with:

yum install httpd

5. Install PostfixAdmin

The latest version of PostfixAdmin, version 3, supports MySQL/MariaDB, PostgreSQL, and SQLite databases. In this guide, we will use MariaDB.
Download the PostfixAdmin archive from SourceForge and extract it in the /var/www/html/ directory:

wget -q -O - "https://downloads.sourceforge.net/project/postfixadmin/postfixadmin/postfixadmin-3.0.2/postfixadmin-3.0.2.tar.gz" | tar -xzf - -C /var/www/html

Open the mail configuration file and edit the following values:

nano /var/www/html/postfixadmin-3.0.2/config.inc.php
$CONF['configured'] = true;
$CONF['database_type'] = 'mysqli';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfixadmin';
$CONF['database_password'] = 'strong_password';
$CONF['database_name'] = 'postfixadmin';

$CONF['domain_path'] = 'NO';
$CONF['domain_in_mailbox'] = 'YES';
chown -R apache: /var/www/html/postfixadmin-3.0.2

To populate the database go to https://Your_IP_Address/postfixadmin-3.0.2/setup.php and you should see something like below:
Testing database connection - OK - mysqli://postfixadmin:xxxxx@localhost/postfixadmin
Everything seems fine... attempting to create/update database structure

Create a new admin user:

bash /var/www/html/postfixadmin-3.0.2/scripts/postfixadmin-cli admin add admin@your_domain_name.com --password strong_password22 --password2 strong_password22 --superadmin 1 --active 1

6. Install and configure postfix

To install postfix run the command bellow:

yum install postfix

Once the installation is completed, we need to create configuration files:

mkdir -p /etc/postfix/sql/
nano /etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query  = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
nano /etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query = SELECT maildir FROM mailbox,alias_domain WHERE alias_domain.alias_domain = '%d' and mailbox.username = CONCAT('%u', '@', alias_domain.target_domain) AND mailbox.active = 1 AND alias_domain.active='1'
nano /etc/postfix/sql/mysql_virtual_alias_domain_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = CONCAT('%u', '@', alias_domain.target_domain) AND alias.active = 1 AND alias_domain.active='1'
nano /etc/postfix/sql/mysql_virtual_alias_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query = SELECT goto FROM alias WHERE address='%s' AND active = '1'
#expansion_limit = 100
nano /etc/postfix/sql/mysql_virtual_domains_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query          = SELECT domain FROM domain WHERE domain='%s' AND active = '1'
#query          = SELECT domain FROM domain WHERE domain='%s'
#optional query to use when relaying for backup MX
#query           = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '0' AND active = '1'
#expansion_limit = 100
nano /etc/postfix/sql/mysql_virtual_mailbox_limit_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query = SELECT quota FROM mailbox WHERE username='%s' AND active = '1'
nano /etc/postfix/sql/mysql_virtual_mailbox_maps.cf
user = postfixadmin
password = strong_password
hosts = localhost
dbname = postfixadmin
query           = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
#expansion_limit = 100

[ecko_alert color=”blue”]Stuck somewhere? Get a VPS from us and we’ll do all of this for you, free of charge! We’ll completely set up and configure a mail server for you. [/ecko_alert]

Edit the main.cf file:

postconf -e "myhostname = $(hostname -f)"
 
postconf -e "virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/mysql_virtual_domains_maps.cf"
postconf -e "virtual_alias_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_catchall_maps.cf"
postconf -e "virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/mysql_virtual_mailbox_maps.cf, proxy:mysql:/etc/postfix/sql/mysql_virtual_alias_domain_mailbox_maps.cf"
 
postconf -e "smtpd_tls_cert_file = /etc/pki/tls/certs/localhost.crt"
postconf -e "smtpd_tls_key_file = /etc/pki/tls/private/localhost.key"
postconf -e "smtpd_use_tls = yes"
postconf -e "smtpd_tls_auth_only = yes"
 
postconf -e "smtpd_sasl_type = dovecot"
postconf -e "smtpd_sasl_path = private/auth"
postconf -e "smtpd_sasl_auth_enable = yes"
postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated, permit_mynetworks, reject_unauth_destination"
 
postconf -e "mydestination = localhost"
postconf -e "mynetworks = 127.0.0.0/8"
postconf -e "inet_protocols = ipv4"
postconf -e "inet_interfaces = all"

postconf -e "virtual_transport = lmtp:unix:private/dovecot-lmtp"

Open the master.cf file, find submission inet n and smtps inet n sections and edit as follows:

nano /etc/postfix/master.cf
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING
smtps     inet  n       -       n       -       -       smtpd
  -o syslog_name=postfix/smtps
#  -o smtpd_tls_wrappermode=yes
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject
  -o milter_macro_daemon_name=ORIGINATING

Enable the postfix service

systemctl enable postfix
systemctl restart postfix

7. Install and Configure Dovecot

Install dovecot with MySQL support using the command bellow:

yum install dovecot dovecot-mysql

Open the /etc/dovecot/conf.d/10-mail.conf file and change the following values:

nano /etc/dovecot/conf.d/10-mail.conf
mail_location = maildir:/var/vmail/%d/%n
mail_privileged_group = mail
mail_uid = vmail
mail_gid = mail
first_valid_uid = 150
last_valid_uid = 150

Open the /etc/dovecot/conf.d/10-auth.conf file and change the following values:

nano /etc/dovecot/conf.d/10-auth.conf
auth_mechanisms = plain login
#!include auth-system.conf.ext
!include auth-sql.conf.ext

Create a new dovecot-sql.conf.ext file:

nano /etc/dovecot/dovecot-sql.conf.ext
driver = mysql
connect = host=localhost dbname=postfixadmin user=postfixadmin password=strong_password
default_pass_scheme = MD5-CRYPT
password_query = SELECT username as user, password, '/var/vmail/%d/%n' as userdb_home, 'maildir:/var/vmail/%d/%n' as userdb_mail, 150 as userdb_uid, 8 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'
user_query = SELECT '/var/vmail/%d/%u' as home, 'maildir:/var/vmail/%d/%u' as mail, 150 AS uid, 8 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'

In the /etc/dovecot/conf.d/10-ssl.conf file enable SSL support:

ssl = yes

Open the /etc/dovecot/conf.d/15-lda.conf file and set the postmaster_address email address.

postmaster_address = postmaster@your_domain_name.com

Open the /etc/dovecot/conf.d/10-master.conf file, find the service lmtp section and change it to:

service lmtp {
  unix_listener /var/spool/postfix/private/dovecot-lmtp {
    mode = 0600
    user = postfix
    group = postfix
  }
}

find the service auth section and change it to:

service auth {
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }
  unix_listener auth-userdb {
    mode = 0600
    user = vmail
    #group = vmail
  }
  user = dovecot
}

Change the service auth-worker section to the following:

service auth-worker {
  user = vmail
}

Set the permissions:

chown -R vmail:dovecot /etc/dovecot
chmod -R o-rwx /etc/dovecot

Enable and restart the dovecot service

systemctl enable dovecot 
systemctl restart dovecot 

8. Install and configure Spamassassin

Install spamassassin using the command bellow:

yum install spamassassin

Create a spamassassin system user:

groupadd spamd
useradd -g spamd -s /bin/false -d /var/log/spamassassin spamd
chown spamd:spamd /var/log/spamassassin

9. Configure Postfix to use SpamAssassin

Open the master.cf file and edit as follows:

nano /etc/postfix/master.cf

change

smtp      inet  n       -       n       -       -       smtpd

with

smtp      inet  n       -       n       -       -       smtpd -o content_filter=spamassassin

add the following line at the end of the file:

spamassassin unix - n n - - pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient}

Enable and restart the spamassassin service

systemctl enable spamassassin 
systemctl restart spamassassin 

Restart the postfix service

systemctl restart postfix

If everything is set up correctly now you should be able to log in to your PostfixAdmin backend by going to http://Your_IP_Address/postfixadmin-3.0.2.2 and create your first virtual domain and mailbox.


Of course, you don’t have to Set up a mail server with PostfixAdmin and MariaDB on CentOS 7,  if you use one of our Mail Server Hosting services, in which case you can simply ask our expert Linux admins to set up a mail server for you. They are available 24×7 and will take care of your request immediately.

PS. If you liked this post, on how to Set up a mail server with PostfixAdmin and MariaDB on CentOS 7,  please share it with your friends on the social networks using the buttons below or simply leave a comment in the Comments Section below. Thanks.

View Comments (87)

  • Hello administrator, I have a problem, my server is like an open relay, when I connect by telnet to port 25 it is possible to send emails. I would like only authenticated users to send emails, how can I do it? Please, could you help me?

  • Good tutorial. With these settings, can we send emails (from the CentOS) to, for example, gmail or hotmail?

      • That's weird. I follow through and through the tutorial and it gave me ZERO errors. However, I tried to send out an email to my gmail account and got nothing. How would I go about troubleshooting this? Should I try to look at the logs (to which I don't know their location)? For reference, I'm running with an internal DNS with forwarding, so maybe the problem is there? Still would not make sense since the GMail record is being resolved.
        Thank you so much for replying and I hope you can help.

        • Yes, you should definitely look into the log files and see what happens when you try to send email. The log file is usually called /var/log/maillog or /var/log/mail.

  • OK, I follow through but I get these errors in the log:
    postfix/sendmail[1424]: fatal: usage: sendmail [options]
    postfix/pipe[1425]: 7092DCC2C7C: to=, relay=spamassassin, delay=62160, delays=62157/0.07/0/2.5, dsn=4.3.0, status=deferred (temporary failure. Command output: sendmail: option requires an argument -- 'f' sendmail: option requires an argument -- 'f' sendmail: fatal: usage: sendmail [options] )
    spamc[1424]: connect to spamd on 127.0.0.1 failed, retrying (#2 of 3): Connection refused
    spamc[1426]: connect to spamd on ::1 failed, retrying (#3 of 3): Connection refused

    • Are you sending the email through the command line or via script? When using -f as option with sendmail you need to specify the envelope sender address as argument. As for the other error message, check if spamd is running.

  • Hi there,

    thanks for this great tutorial. But for the moment I have 2 problems:
    a) when I want to send a mail via postfix.admin I receiv in the maillog a "warning: non-SMTP command from localhost[127.0.0.1]: To: "
    b) when I create a new Mailboxuser the folderstructur under /var/vmail ist not created

    Any Ideas, where I can search for?

    Kind regards
    Oliver

    • a) This is a warning message and it notifies you that non-SMTP command is being sent. You can do a research on Google for more information about how to fix this.
      b) The directories should be created once you log in via IMAP. If they are not created, check this file permissions and if there is a problem you can fix them using:

      chmod -R 770 /var/vmail
      chown -R vmail:mail /var/vmail
  • Hi,
    This tutorial was very helpful for me. But I have a question about modyfing this configuration for use in multidomain/multiIP environment? Standard configuration of postfix multiinstance will be correct? Could You show me some tips about it?

  • with this tutorial is it possible to send emails with SMTP authentication ?.
    I can not, even when I send only internally.

    Dec 4 20:21:19 centos-transacional postfix/qmgr[12996]: 3333620474D6: from=, size=779, nrcpt=1 (queue active)
    Dec 4 20:21:19 centos-transacional postfix/lmtp[13666]: 3333620474D6: to=, relay=none, delay=357, delays=357/0.07/0/0, dsn=4.4.1, status=deferred (connect to centos-transacional.automate.center[private/dovecot-lmtp]: Connection refused)

  • Hi, thanks for sharing your knowledge, please could you tell me how can I do the mailbox quota warning?, for example when is over 95 %.