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


mail server with postfixadmin and mariadb on centos

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

Update the system and install necessary packages

yum update && yum install wget nano

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

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

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

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:[email protected]/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 [email protected]_domain_name.com --password strong_password22 --password2 strong_password22 --superadmin 1 --active 1

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
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.

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

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 = [email protected]_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 

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

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 do any of this 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 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.

Tutorials
How to install VirtueMart with Joomla on a Linux VPS
Tutorials
How to Install PHP-Fusion 9 on a Debian 8 VPS
Tutorials
How to Set up Nginx Server Blocks on Ubuntu and CentOS
  • marian

    marianmarian

    Author Reply

    I followed your tutorial but i get the following error in logs.

    private/dovecot-lmtp]: No such file or directory)


    • admin

      adminadmin

      Author Reply

      Please double check your dovecot configuration (10-master.conf).


  • marian

    marianmarian

    Author Reply

    unfortunately I could not find the issue in 10-master.conf file.


    • admin

      adminadmin

      Author Reply

      The tutorial is tested and it is working.

      Please follow the instructions closely.


  • Muhammad Tahir Minhas

    I Have followed all the step but is give this error on “populating the database”

    Postfix Admin Setup Checker

    Running software:

    PHP version 5.4.16
    Apache/2.4.6 (CentOS) OpenSSL/1.0.1e-fips PHP/5.4.16
    Checking for dependencies:

    Magic Quotes: Disabled – OK
    Depends on: presence config.inc.php – OK
    Checking $CONF[‘configured’] – OK
    Smarty template compile directory is writable – OK
    Error: There is no database support in your PHP setup
    To install MySQL 3.23 or 4.0 support on FreeBSD:
    % cd /usr/ports/databases/php5-mysql/
    % make clean install
    – or with portupgrade –
    % portinstall php5-mysql
    To install MySQL 4.1 support on FreeBSD:
    % cd /usr/ports/databases/php5-mysqli/
    % make clean install
    – or with portupgrade –
    % portinstall php5-mysqli
    To install PostgreSQL support on FreeBSD:
    % cd /usr/ports/databases/php5-pgsql/
    % make clean install
    – or with portupgrade –
    % portinstall php5-pgsql
    Error: Can’t connect to database
    Please edit the $CONF[‘database_*’] parameters in config.inc.php.
    DEBUG INFORMATION:
    MySQL 4.1 functions not available! (php5-mysqli installed?)
    database_type = ‘mysqli’ in config.inc.php, are you using a different database?

    Depends on: session – OK
    Depends on: pcre – OK
    Depends on: multibyte string – OK
    Warning: Depends on: IMAP functions – NOT FOUND
    To install IMAP support, install php5-imap
    Without IMAP support, you won’t be able to create subfolders when creating mailboxes.


    • admin

      adminadmin

      Author Reply

      You should install php mysql and imap extensions

      yum install php-mysql php-imap


  • Muhammad Tahir Minhas

    when i add these lines to main.cf then service want start please help me

    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”


    • admin

      adminadmin

      Author Reply

      What error do you get in your mail log file ?


      • Muhammad Tahir Minhas

        Dear Admin,

        This the log file

        Jun 6 14:59:03 mail postfix/sendmail[1524]: warning: macro name syntax error: “hostnam
        e -f”
        Jun 6 14:59:03 mail postfix/sendmail[1524]: fatal: dictionary mail_dict: macro process
        ing error


        • admin

          adminadmin

          Author Reply

          Open the main.cf file and set the myhostname value to your server hostname.


  • comprar movil

    where/when you generate these certs?

    postconf -e “smtpd_tls_cert_file = /etc/pki/tls/certs/localhost.crt”
    postconf -e “smtpd_tls_key_file = /etc/pki/tls/private/localhost.key”


    • admin

      adminadmin

      Author Reply

      On a CentOS/RedHat server, these certificate and key are generated by default.


  • Muhammad Tahir Minhas

    Can you please guide me how to configure squirrelmail with postfixadmin


  • Muhammad Tahir Minhas

    This email address already exists please choose a different one. Gives this error when creating the alias. Please can you guide the solution.


    • admin

      adminadmin

      Author Reply

      Open the mail configuration file (config.inc.php) and edit the following line (set it to YES):

      $CONF['alias_control'] = 'YES';

      Then try creating the email address again


      • Muhammad Tahir Minhas

        Dear Admin,

        Its already set to YES.


        • admin

          adminadmin

          Author Reply

          Did you try using a different alias?


          • Muhammad Tahir Minhas

            different aliases are created but if i use existing email for forwarding then this issue arise.


          • Muhammad Tahir Minhas

            Dear Admin,

            You deleted my previous comment but don’t give me the answer.


  • Muhammad Tahir Minhas

    Basically i want to configure email forwarding for the existing user to different email. Like in Exchange Server


    • admin

      adminadmin

      Author Reply

      What error do you get when you try to create an alias, are you sure you installed postfixadmin correctly ?


      • Muhammad Tahir Minhas

        Yes i am sure configurations are ok.
        And this is the error below:

        This email address already exists, please choose a different one!


        • admin

          adminadmin

          Author Reply

          You should be able to edit the aliases for the email address that already exists through the postfixadmin dashboard.


  • Muhammad Tahir Minhas

    Thanks,

    Can you guide me how to restrict specific users not to send email outside the domain.


  • Jeet

    JeetJeet

    Author Reply

    Only we need to create db postfixadmin? Do we have to create table or db for virtual domain, alias?


    • admin

      adminadmin

      Author Reply

      You only need to create database for postfixadmin.

      Thanks.


  • Gurjeet

    GurjeetGurjeet

    Author Reply

    Do we need to create any other DB or table for Virtual Domain, user, alias?


  • sahi

    sahisahi

    Author Reply

    Please advise what protocols I need to set for email client
    getting smtp error – I have configured for thunderbird 587
    Imap I have configured 143


    • admin

      adminadmin

      Author Reply

      Hi Sahi,

      If you are using IMAP, make sure that you select SSL (port 993)


  • waleed

    waleedwaleed

    Author Reply

    please I have a issues 0.03/0/0, dsn=4.4.1, status=deferred (connect to ns1.test66.pv[private/dovecot-lmtp]: No such file or directory


  • noway

    nowaynoway

    Author Reply

    Yea, I can see where they are having problems, I got to dovecot install 10-mail.conf
    mail_location = maildir:/var/vmail/%d/%n
    which doesn’t match your postfixadmin config

    $CONF[‘domain_path’] = ‘NO’;
    $CONF[‘domain_in_mailbox’] = ‘YES’;


  • Ramon

    RamonRamon

    Author Reply

    Hi, thanks for your guide.

    I have one issue in my configuration because I cant not receive mails. Can you help me?
    Regards


    • admin

      adminadmin

      Author Reply

      Hello Ramon,

      Please check your log files for errors. It will help you to track and fix the problem.

      Thanks.


  • Cico

    CicoCico

    Author Reply

    Hi,
    thanks for this wonderful guide!
    I’ve followed step by step closely, and my mail server is setup, except for the spamassassin part… when I enable the filter, I can’t recive email anymore from the external world, senders receive a reply back saying message undelivered:
    Final-Recipient: rfc822; [email protected]
    Original-Recipient: rfc822;[email protected]
    Action: failed
    Status: 5.3.0
    Diagnostic-Code: x-unix; service unavailable

    If I remove the -o content_filter=spamassassin and spamassassin unix – n n – – pipe flags=R user=spamd argv=/usr/bin/spamc -e /usr/sbin/sendmail -oi -f ${sender} ${recipient} at the end of the file, mailflow works perfectly (even alias).
    What can be the issue here?
    PS: in the rejected email if I look at the rejected message I can se the [SPAM] in the email subject…so something is happening with spamassassin engine that refuse email without delivering them.

    Thanks for any help you would provide and for your time.
    Cico.


    • admin

      adminadmin

      Author Reply

      Hi,

      It may be a configuration issue. Did you check the mail log files?


  • Haythum Osman

    Hello,

    I follow the steps & everything is fine, when I tried to login to the Postfix Admin using the admin email & password it keeps getting back to the same form.
    When i entered a wrong password, it did give password error message!

    Will you help me please.

    best regards,


    • admin

      adminadmin

      Author Reply

      Hi Haythum,

      Make sure that you closely followed the installation steps and you properly configured PostfixAdmin.


 
Free Migration to RoseHosting. Award Winning Linux VPS Hosting with Fully Managed Support. Coupon RHBLOG50 for 50% offOrder Now
+