Recently setup a new email server on a CentOS Rocky 9 VPS server and thought I would document the process below. I pulled information from a variety of webpages and will try to give the sources and credit where applicable.

While running your own email will take a little time and require occasional maintenance there are benefits of running your own email server such as being able to create many mailboxes (email addresses) without extra cost, and mailbox sizes limited only by the server storage size.

On the downsides, you will be responsible for maintenance tasks such as resolving issues with the server, upgrading software, setting up and renewing SSL certificates, and other server administration tasks.

Also, while not covered in this guide, additional configuration will be required if sending email to more struct servers (such as Microsoft and Google gmail) are desired. In order to combat spam some email servers have implemented very strict requirements for accepting incoming mail. Some of the additional required configuration includes setting up one or more of the following:
SPF (Sender Policy Framework)
DMARC (Domain-based Message Authentication, Reporting and Conformance)
DKIM (DomainKeys Identified Mail)

While the above additional configuration is not impossible to do it does require a little more time to get all the configuration settings correctly configured. Perhaps I will cover how to set these items up in an upcoming post.

Here is a brief explanation of the parts:
MariaDB (mySQL) or PostgreSQL
the database where persistent data is stored, either MySQL or PostgreSQL
postfix
handles incoming SMTP connections to the server and routes email to local email boxes
handles outgoing SMTP connections to deliver email to other mail servers (through SMTP)
dovecot
handles POP3 and IMAP connections to the server
handles connections from mail clients to allow accessing a mailbox downloading of mail
postfixadmin
management interface to manage domains, mailboxes (email addresses), and passwords
roundcubemail
a PHP web based email client to allow users of the system easy access to mailboxes

This guide begins with a fresh install of CentOS Rocky 9 and using ssh to connect to the server.
All the commands here will be run under the root account unless otherwise specified.
This will avoid having to use sudo for all the commands and fixing permissions later.

The server can be setup with either MySQL (MariaDB) or PostgreSQL as the database. The database will be storing mail account information (login user/password) and other mail routing information. In the past I have used MySQL a lot but recently been leaning towards PostgreSQL.

As of this guide the following versions were used:
Rocky Linux release 9.4 (Blue Onyx)
php 8.0.30
MariaDB 8.0.36
PostgreSQL 13.16
postfix 3.5.9-24
dovecot 2.3.16
postfixadmin 3.3.13
roundcubemail 1.6.9-complete

Step 1: Update the server

First up we should make sure the system is up to date on updates.

yum update

Step 2: Install useful utilities

#enable useful packages
yum install epel-release
#install useful utilities
yum install screen rsync wget tar

Step 3: Install the database (MySQL)

We will actually be using MariaDB (an actively developed open source fork of MySQL by the original developers).

yum install mysql-server
systemctl enable mysql
systemctl start mysql

mysql_secure_installation
*** reply yes to all the questions for the most secure installation

Step 3: Install the database (PostgreSQL)

yum install postgresql-server glibc-all-langpacks
postgresql-setup --initdb
systemctl enable postgresql
systemctl start postgresql

Step 4: Setup the database (MySQL)

mysql
CREATE DATABASE postfix;
GRANT ALL ON postfix.* TO 'postfix'@'localhost' IDENTIFIED BY 'postfix_password';
FLUSH PRIVILEGES;
\q

Step 4: Setup the database (PostgreSQL)

By default PostgreSQL does not have password authentication enabled, which postfix will need.
Enable password authentication from the local server by editing the following file and making the following change to the configuration. This will enable md5 (password) authentication from the ip address 127.0.0.1 (local host).

/var/lib/pgsql/data/pg_hba.conf

# IPv4 local connections:
#host    all             all             127.0.0.1/32            ident
host    all             all             127.0.0.1/32            md5

Finally restart the PostgreSQL service using the following command:

systemctl restart postgresql

Now create the empty database and login for postfix.

su postgres
psql
CREATE USER postfix WITH PASSWORD 'postfix_password';
CREATE DATABASE postfix OWNER postfix ENCODING 'unicode';
\q
exit

Step 5: Create the vmail user

Setup the account and folders for virtual mail.
For security reasons, a new user should be created to store the mails.

A gid and uid of 5000 is used in both cases so that we do not run into conflicts with regular users. All your mail will then be stored in /home/vmail. You could change the home directory to something like /var/mail/vmail or /var/vmail but be careful to change this in any configuration below as well.

groupadd -g 5000 vmail
useradd -u 5000 -g vmail -s /usr/bin/nologin -d /home/vmail -m vmail

Step 6: Install postfix

yum install postfix

If using PostfixSQL install the postfix-pgsql extension.
MySQL is supported by default.

#only required if using PostgreSQL
yum install postfix-pgsql

Step 7: Setup postfix main.cf (common)

Edit the configuration file and change the following configuration.

/etc/postfix/main.cf

Change myhostname to the mail server domain (or subdomain) name

myhostname = mail.example.com

Change the inet_interfaces setting to all to allow incoming connections.

inet_interfaces = all
#inet_interfaces = $myhostname
#inet_interfaces = $myhostname, localhost
#inet_interfaces = localhost

Change the inet_protocols setting if ipv6 is not supported or errors are encountered during postfix service startup.
In my cause I needed to make the following change to avoid postfix service startup errors.

# Enable IPv4, and IPv6 if supported
#inet_protocols = all
inet_protocols = ipv4

Change the smtpd_tls_cert_file and smtpd_tls_key_file to point to the SSL certificates.

#smtpd_tls_cert_file = /etc/pki/tls/certs/postfix.pem
smtpd_tls_cert_file = /home/autossl/ssl/mail.example.com/mail.example.com.combined.crt
#smtpd_tls_key_file = /etc/pki/tls/private/postfix.key
smtpd_tls_key_file = /home/autossl/ssl/mail.example.com/mail.example.com.key.pem

Step 8: Setup postfix main.cf (MySQL)

Add the virtual mail configuration to the bottom of the configuration file.

/etc/postfix/main.cf

# Virtual Mailbox Domain Settings

relay_domains = $mydestination, proxy:mysql:/etc/postfix/mysql/relay_domains.cf

#choose this or the below
# For non-alias domains functionality uncomment the one line below
#virtual_alias_maps = proxy:mysql:/etc/postfix/mysql/virtual_alias_maps.cf

#choose this or the above
# For alias domains functionality uncomment the two lines below
virtual_alias_maps = proxy:mysql:/etc/postfix/mysql/virtual_alias_maps.cf,proxy:mysql:/etc/postfix/mysql/virtual_alias_domains_maps.cf
virtual_alias_domains = proxy:mysql:/etc/postfix/mysql/virtual_alias_domains.cf

virtual_mailbox_domains = proxy:mysql:/etc/postfix/mysql/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/mysql/virtual_mailbox_maps.cf

virtual_mailbox_limit = 104857600
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_base = /home/vmail
virtual_transport = virtual
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
#transport_maps = lmdb:/etc/postfix/transport

smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/spool/postfix/private/auth
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3

message_size_limit = 52428800
mailbox_size_limit = 104857600

Step 8: Setup postfix main.cf (PostfixSQL)

Add the virtual mail configuration to the bottom of the configuration file.

/etc/postfix/main.cf

# Virtual Mailbox Domain Settings

relay_domains = $mydestination, proxy:pgsql:/etc/postfix/pgsql/relay_domains.cf

#choose this or the below
# For non-alias domains functionality uncomment the one line below
#virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_maps.cf

#choose this or the above
# For alias domains functionality uncomment the two lines below
virtual_alias_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_maps.cf,proxy:pgsql:/etc/postfix/pgsql/virtual_alias_domains_maps.cf
virtual_alias_domains = proxy:pgsql:/etc/postfix/pgsql/virtual_alias_domains.cf

virtual_mailbox_domains = proxy:pgsql:/etc/postfix/pgsql/virtual_domains_maps.cf
virtual_mailbox_maps = proxy:pgsql:/etc/postfix/pgsql/virtual_mailbox_maps.cf

virtual_mailbox_limit = 104857600
virtual_minimum_uid = 5000
virtual_uid_maps = static:5000
virtual_gid_maps = static:5000
virtual_mailbox_base = /home/vmail
virtual_transport = virtual
local_transport = virtual
local_recipient_maps = $virtual_mailbox_maps
#transport_maps = lmdb:/etc/postfix/transport

smtpd_sasl_type = dovecot
smtpd_sasl_path = /var/spool/postfix/private/auth
smtpd_use_tls=yes
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtpd_tls_security_level=may
smtpd_tls_protocols = !SSLv2, !SSLv3

message_size_limit = 52428800
mailbox_size_limit = 104857600

Step 9: Create database query configuration (MySQL)

/etc/postfix/mysql/relay_domains.cf

# relay_domains.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = true

/etc/postfix/mysql/virtual_alias_maps.cf

# virtual_alias_maps.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
table = alias
select_field = goto
where_field = address

/etc/postfix/mysql/virtual_domains_maps.cf

# virutal_domains_maps.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
table = domain
select_field = domain
where_field = domain
additional_conditions = and backupmx = '0' and active = '1'

/etc/postfix/mysql/virtual_mailbox_limits.cf

# virtual_mailbox_limits.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
table = mailbox
select_field = quota
where_field = username
additional_conditions = and active = '1'

/etc/postfix/mysql/virtual_mailbox_maps.cf

# virtual_mailbox_maps.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
table = mailbox
select_field = maildir
where_field = username
additional_conditions = and active = '1'

/etc/postfix/mysql/virtual_sender_maps.cf

# virtual_sender_maps.cf
# mysql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT username FROM mailbox WHERE username='%s' AND active = true

/etc/postfix/mysql/virtual_alias_domains.cf

INSERT CODE HERE

/etc/postfix/mysql/virtual_alias_domains_maps.cf

INSERT CODE HERE

Step 9: Create database query configuration (PostgreSQL)

/etc/postfix/pgsql/relay_domains.cf

# relay_domains.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT domain FROM domain WHERE domain='%s' and backupmx = true

/etc/postfix/pgsql/virtual_alias_maps.cf

# virtual_alias_maps.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias WHERE address='%s' AND active = true

/etc/postfix/pgsql/virtual_domains_maps.cf

# virutal_domains_maps.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
#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 = false and active = true

/etc/postfix/pgsql/virtual_mailbox_limits.cf

# virtual_mailbox_limits.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT quota FROM mailbox WHERE username='%s'

/etc/postfix/pgsql/virtual_mailbox_maps.cf

# virtual_mailbox_maps.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = true

/etc/postfix/pgsql/virtual_sender_maps.cf

# virtual_sender_maps.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT username FROM mailbox WHERE username='%s' AND active = true

/etc/postfix/pgsql/virtual_alias_domains.cf

# virtual_alias_domains.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT alias_domain FROM alias_domain WHERE alias_domain='%s' AND active = '1'

/etc/postfix/pgsql/virtual_alias_domains_maps.cf

# virtual_alias_domains_maps.cf
# postgresql
user = postfix
password = postfix_password
hosts = localhost
dbname = postfix
query = SELECT goto FROM alias,alias_domain WHERE alias_domain.alias_domain = '%d' and alias.address = '%u' || '@' || alias_domain.target_domain AND alias.active = '1' AND alias_domain.active='1'

Step 10: Setup postfix master.cf

Make the following changes to the master.cf file.

/etc/postfix/master.cf
#
# Postfix master process configuration file.  For details on the format
# of the file, see the master(5) manual page (command: "man 5 master" or
# on-line: http://www.postfix.org/master.5.html).
#
# Do not forget to execute "postfix reload" after editing this file.
#
# ==========================================================================
# service type  private unpriv  chroot  wakeup  maxproc command + args
#               (yes)   (yes)   (no)    (never) (100)
# ==========================================================================
smtp      inet  n       -       n       -       -       smtpd
#smtp      inet  n       -       n       -       1       postscreen
#smtpd     pass  -       -       n       -       -       smtpd
#dnsblog   unix  -       -       n       -       0       dnsblog
#tlsproxy  unix  -       -       n       -       0       tlsproxy
submission inet n       -       n       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_tls_auth_only=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=permit_sasl_authenticated,reject
#  -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
#628       inet  n       -       n       -       -       qmqpd
.
.
.

Step 11: Start postfix service

If everything was setup correctly we should be able to startup the postfix service without error with the below command.

systemctl start postfix

Step 12: Install dovecot

Dovecot is the software that allows access the mailbox using the pop3 or imap protocol. This is the service being connected to when accessing a mailbox from an email client.

yum install dovecot

If using PostfixSQL install the dovecot-pgsql extension.
MySQL is supported by default.

#only required if using PostgreSQL
yum install dovecot-pgsql

Step 13: Setup dovecot dovecot.conf

Change configuration in the dovecot.conf file.

/etc/dovecot/dovecot.conf

Change the protocols setting, this determines which protocols will be available.
In my case I chose to enable only IMAP.

#protocols = imap pop3 lmtp
protocols = imap

Step 14: Setup dovecot 10-auth.conf

Change dovecot authentication settings in the below file.

/etc/dovecot/conf.d/10-auth.conf

#!include auth-deny.conf.ext
#!include auth-master.conf.ext

#!include auth-system.conf.ext
!include auth-sql.conf.ext
#!include auth-ldap.conf.ext
#!include auth-passwdfile.conf.ext
#!include auth-checkpassword.conf.ext
#!include auth-static.conf.ext

Step 15: Setup dovecot 10-mail.conf

Change the dovecot virtual mail directory setting.

/etc/dovecot/conf.d/10-mail.conf

#mail_location =
mail_location = /home/vmail/%d/%n

Step 16: Setup dovecot 10-ssl.conf

Change the dovecot SSL certificate settings to point to the SSL certificates.

/etc/dovecot/conf.d/10-ssl.conf

#ssl_cert = </etc/pki/dovecot/certs/dovecot.pem
#ssl_key = </etc/pki/dovecot/private/dovecot.pem
ssl_cert = </home/autossl/ssl/mail.example.com/mail.example.com.combined.crt
ssl_key = </home/autossl/ssl/mail.example.com/mail.example.com.key.pem

Step 17: Setup dovecot 10-master.conf

Change the dovecot authentication service which postfix connects to. This will be used for postfix to validate smtp connections. This needs to match the smtpd_sasl_path setting in /etc/postfix/main.cf above.

/etc/dovecot/conf.d/10-master.conf

service auth {
  # auth_socket_path points to this userdb socket by default. It's typically
  # used by dovecot-lda, doveadm, possibly imap process, etc. Users that have
  # full permissions to this socket are able to get a list of all usernames and
  # get the results of everyone's userdb lookups.
  #
  # The default 0666 mode allows anyone to connect to the socket, but the
  # userdb lookups will succeed only if the userdb returns an "uid" field that
  # matches the caller process's UID. Also if caller's uid or gid matches the
  # socket's uid or gid the lookup succeeds. Anything else causes a failure.
  #
  # To give the caller full permissions to lookup all users, set the mode to
  # something else than 0666 and Dovecot lets the kernel enforce the
  # permissions (e.g. 0777 allows everyone full permissions).
  unix_listener auth-userdb {
    #mode = 0666
    #user =
    #group =
  }

  # Postfix smtp-auth
  unix_listener /var/spool/postfix/private/auth {
    mode = 0666
    user = postfix
    group = postfix
  }

  # Auth process is run as this user.
  #user = $default_internal_user
}

Step 18: Setup dovecot dh.pem (option)

I believe this is optional but may add security to dovecot by enabling the ssl_dh setting and generating a new dh.pem.

Uncomment the ssl_dh setting in 10-ssl.conf.

/etc/dovecot/conf.d/10-ssl.conf

ssl_dh = </etc/dovecot/dh.pem

Now generate a new dh.pem, this will take several minutes (about 15 minutes when I did it).

openssl dhparam -out /etc/dovecot/dh.pem 4096

Step 19: Create the dovecot-sql.conf.ext settings file (MySQL)

/etc/dovecot/dovecot-sql.conf.ext

Place the below contents into the file.

driver = mysql

connect = host=localhost dbname=postfix user=postfix password=postfix_password

# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes

# Default password scheme - change to match your Postfixadmin setting.
# depends on your $CONF['encrypt'] setting:
#           -> SHA512-CRYPT
# md5crypt  -> MD5-CRYPT
# md5       -> PLAIN-MD5
# cleartext -> PLAIN
default_pass_scheme = MD5-CRYPT

# Get the mailbox
user_query = SELECT '/home/vmail/%d/%n' as home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'

# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'

# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user

Step 19: Create the dovecot-sql.conf.ext settings file (PostgreSQL)

/etc/dovecot/dovecot-sql.conf.ext

Place the below contents into the file.

driver = pgsql

connect = host=localhost dbname=postfix user=postfix password=postfix_password

# It is highly recommended to not use deprecated MD5-CRYPT. Read more at http://wiki2.dovecot.org/Authentication/PasswordSchemes

# Default password scheme - change to match your Postfixadmin setting.
# depends on your $CONF['encrypt'] setting:
#           -> SHA512-CRYPT
# md5crypt  -> MD5-CRYPT
# md5       -> PLAIN-MD5
# cleartext -> PLAIN
default_pass_scheme = MD5-CRYPT

# Get the mailbox
user_query = SELECT '/home/vmail/' || maildir AS home, 'maildir:/home/vmail/%d/%n' as mail, 5000 AS uid, 5000 AS gid, concat('dirsize:storage=',  quota) AS quota FROM mailbox WHERE username = '%u' AND active = '1'

# Get the password
password_query = SELECT username as user, password, '/home/vmail/%d/%n' as userdb_home, 'maildir:/home/vmail/%d/%n' as userdb_mail, 5000 as  userdb_uid, 5000 as userdb_gid FROM mailbox WHERE username = '%u' AND active = '1'

# If using client certificates for authentication, comment the above and uncomment the following
#password_query = SELECT null AS password, ‘%u’ AS user

Step 20: Start the dovecot service

If everything got configured correctly then we should be able to startup the dovecot service without error.

systemctl enable dovecot
systemctl start dovecot

Step 21: Install postfixadmin

Postfix will allow easy administration of the domains, mailboxes, and passwords.

PHP will need to be installed if not

yum install php

Grab the latest version of postfixadmin (this guide was written with version 3.3.13 which will be provided here as a download). I would recommend the latest stable version but it is possible the configuration file has changed. Either download the latest version or download version 3.3.13 (hosted here).

wget https://github.com/postfixadmin/postfixadmin/archive/refs/tags/postfixadmin-3.3.13.tar.gz

Extract the contents and rename the folder and move it to the website folder.

tar -zxvf postfixadmin-3.3.13.tar.gz
mv postfixadmin-postfixadmin-3.3.13 postfixadmin
mv postfixadmin /var/www/vhosts/mail.example.com/html/.

Create the tempaltes_c folder and set permissions to allow the web server to write to it.

mkdir -p /var/www/vhosts/mail.example.com/html/postfixadmin/templates_c
chmod 777 /var/www/vhosts/mail.example.com/html/postfixadmin/templates_c

Create a setup password, an example is given below, feel free to generate your own custom password (it will be more secure).

php -r “echo password_hash(‘the_setup_password’, PASSWORD_DEFAULT);”
$2y$10$6tf/jIc3PQWzrjDdMUFEtu10zgQlll5I/lmiMcAC7JOm/X.RI5nLi

Copy this setup password (along with other settings) into the config.local.php file below. A more secure configuration would use a separate database user (ex. postfixadmin) instead of the postfix database user (postfix) however this is optional. The “encrypt” setting must match the above postfix settings and dovecot settings. If using PostgreSQL comment out the database_type mysqli and uncomment the database_type pgsql lines.

If using PostgreSQL be sure to install the php extension for it.
The MySQL extension comes installed by default with PHP.

#only required if using PostgreSQL
yum install php-pgsql

/var/www/vhosts/mail.example.com/html/postfixadmin/config.local.php

<?php
$CONF['database_type'] = 'mysqli';
//$CONF['database_type'] = 'pgsql';
$CONF['database_host'] = 'localhost';
$CONF['database_user'] = 'postfix';
$CONF['database_password'] = 'postfix_password';
$CONF['database_name'] = 'postfix';
//$CONF['encrypt'] = 'dovecot:SHA512';
$CONF['encrypt'] = 'md5crypt';
$CONF['configured'] = true;
$CONF['setup_password'] = '$2y$10$6tf/jIc3PQWzrjDdMUFEtu10zgQlll5I/lmiMcAC7JOm/X.RI5nLi';

$CONF['domain_path'] = 'YES';
$CONF['domain_in_mailbox'] = 'NO';
?>

Step 22: Setup postfixadmin

Open up the postfixadmin setup URL in a web browser to create the admin account.

https://mail.example.com/postfixadmin/setup.php

Once the admin account is created login and create a domain, also create one or more mailboxes.

Step 23: Install roundcubemail

Roundcubemail will provide an easy to use HTML mail client for users of the mail system. This is optional but will make accessing mail easy with just a web browser without needing to configure an email client.

If not installed already the following PHP extensions should be installed now.

yum install php-intl php-zip

Grab the latest version of roundcubemail (this guide was written with version 1.6.9 which will be provided here as a download). I would recommend the latest stable version but it is possible the configuration file has changed. Either download the latest version or download version 1.6.9 (hosted here).

wget https://github.com/roundcube/roundcubemail/releases/download/1.6.9/roundcubemail-1.6.9-complete.tar.gz

Extract the contents and rename the folder and move it to the website folder.

tar -zxvf roundcubemail-1.6.9-complete.tar.gz
mv roundcubemail-1.6.9 roundcubemail
mv roundcubemail /var/www/vhosts/mail.example.net/html/.

Copy the default configuration template and customize it with the required settings.

cp /var/www/vhosts/mail.example.net/html/roundcubemail/config/config.inc.php.sample /var/www/vhosts/mail.example.net/html/roundcubemail/config/config.inc.php

Open up the copied configuration file and change the below settings to match our setup.
This includes the database connection settings (required to store user preferences) along with the URLs to the incoming and outgoing server settings. The imap_host and smtp_host should point to the server ip address. If using PostgreSQL comment out the line with “mysql” and uncomment the line with “pgsql” to match the database being used.

$config['db_dsnw'] = 'mysql://roundcube:roundcube_password@localhost/roundcubemail';
//$config['db_dsnw'] = 'pgsql://roundcube:roundcube_password@localhost/roundcubemail';
$config['imap_host'] = 'ssl://mail.example.net';
$config['smtp_host'] = 'tls://smtp.example.net';

Step 24: Setup roundcubemail database (MySQL)

Create the database structure for roundcubemail by executing the following commands.
Create the roundcube database and associated user.

mysql
CREATE DATABASE roundcube;
GRANT ALL ON roundcube.* TO 'roundcube'@'localhost' IDENTIFIED BY 'roundcube_password';
FLUSH PRIVILEGES;
\q

Import the roundcube database structure into the database.

mysql roundcube < /var/www/vhosts/mail.example.com/html/roundcubemail/SQL/mysql.initial.sql

Step 24: Setup roundcubemail database (PostgreSQL)

Create the database structure for roundcubemail by executing the following commands.
Create the roundcube database and associated user.

su postgres
psql
CREATE USER roundcube WITH PASSWORD 'roundcube_password';
CREATE DATABASE roundcubemail OWNER roundcube ENCODING 'unicode';
¥q
exit

Import the roundcube database structure into the database.

psql -h 127.0.0.1 -d roundcubemail -U roundcube -W -f /var/www/vhosts/mail.example.com/html/roundcubemail/SQL/postgres.initial.sql
* use the password roundcube_password when prompted

Step 25: Open with web browser and check

Open up the roundcubemail webpage with a web browser and attempt to login to a mailbox (if one was created above).

https://mail.example.com/roundcubemail

Step 26: Conclusion

This should complete the full setup with postfix, dovecot, postfixadmin and roundcubemail. I am planning on making a video soon detailing all these above steps.

Leave a Reply

Your email address will not be published. Required fields are marked *