The Perfect Server - CentOS 7 x86_64 (nginx, Dovecot, ISPConfig 3)

Version 1.0
Authors: Till Brehm, Srijan Kishore and Falko Timme
Follow howtoforge on Twitter

This tutorial shows how to prepare a CentOS 7 x86_64 server for the installation of ISPConfig 3, and how to install ISPConfig 3 on it. ISPConfig 3 is a webhosting control panel that allows you to configure the following services through a web browser: nginx web server, Postfix mail server, MySQL, BIND nameserver, PureFTPd, SpamAssassin, ClamAV, Mailman, and many more. Since version 3.0.4, ISPConfig comes with full support for the nginx web server in addition to Apache; this tutorial covers the setup of a server that uses nginx, not Apache. The ISPConfig 3 apache perfect server tutorial is available here.


1. Requirements

To install such a system you will need the following


2. Preliminary Note

In this tutorial I use the hostname with the IP address and the gateway These settings might differ for you, so you have to replace them where appropriate. Please install the minimal CentOS 7 installation from this tutorial link before proceeding ahead.


3 Install nano editor and adjust /etc/hosts

yum -y install nano wget

Next we edit /etc/hosts. Make it look like this:

nano /etc/hosts   localhost localhost.localdomain localhost4 localhost4.localdomain4     server1

::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

and set the hostname to

echo '' > /etc/hostname


4 Configure The Firewall and install some basic network software

(You can skip this chapter if you have already disabled the firewall at the end of the basic system installation.)

I want to install ISPConfig at the end of this tutorial which comes with its own firewall. That's why I disable the default CentOS firewall now. Of course, you are free to leave it on and configure it to your needs (but then you shouldn't use any other firewall later on as it will most probably interfere with the CentOS firewall).


systemctl stop firewalld.service
systemctl disable firewalld.service

[root@server1 ~]# systemctl disable firewalld.service
rm '/etc/systemd/system/dbus-org.fedoraproject.FirewallD1.service'
rm '/etc/systemd/system/'
[root@server1 ~]#

and disable the firewall.

To check that the firewall has really been disabled, you can run

firewall-cmd --state

afterwards. The output should look like this:

[root@server1 ~]# firewall-cmd --state
not running
[root@server1 ~]#

yum -y install net-tools NetworkManager-tui

5 Disable SELinux

SELinux is a security extension of CentOS that should provide extended security. In my opinion you don't need it to configure a secure system, and it usually causes more problems than advantages (think of it after you have done a week of trouble-shooting because some service wasn't working as expected, and then you find out that everything was ok, only SELinux was causing the problem). Therefore I disable it (this is a must if you want to install ISPConfig later on).

Edit /etc/selinux/config and set SELINUX=disabled:

nano /etc/selinux/config

# This file controls the state of SELinux on the system.
# SELINUX= can take one of these three values:
#     enforcing - SELinux security policy is enforced.
#     permissive - SELinux prints warnings instead of enforcing.
#     disabled - No SELinux policy is loaded.
# SELINUXTYPE= can take one of these two values:
#     targeted - Targeted processes are protected,
#     mls - Multi Level Security protection.

Afterwards we must reboot the system:



6 Enable Additional Repositories And Install Some Software

We will enable EPEL repositories on our CentOS system as lots of the packages that we are going to install in the course of this tutorial are not available in the official CentOS 7.0 repositories:

yum -y install epel-release

yum -y install yum-priorities

Edit /etc/yum.repos.d/epel.repo...

nano /etc/yum.repos.d/epel.repo

... and add the line priority=10 to the [epel] section:

name=Extra Packages for Enterprise Linux 7 - $basearch


Then we update our existing packages on the system:

yum update

Now we install some software packages that are needed later on:

yum -y groupinstall 'Development Tools'


7 Quota

(If you have chosen a different partitioning scheme than I did, you must adjust this chapter so that quota applies to the partitions where you need it.)

To install quota, we run this command:

yum -y install quota

Now we check if quota is already enabled for the filesystem where the website (/var/www) and maildir data (var/vmail) is stored. In this example setup, I have one big root partition, so I search for ' / ':

mount | grep ' / '

[root@server1 ~]# mount | grep ' / '
/dev/mapper/centos-root on / type xfs (rw,relatime,attr2,inode64,noquota)
[root@server1 ~]#

If you have a separate /var partition, then use:

mount | grep ' /var '

instead. If the line contains the word "noquota", then proceed with the following steps to enable quota.


Enabling quota on the / (root) partition

Normally you would enable quota in the /etc/fstab file, but if the filesystem is the root filesystem "/", then quota has to be enabled by a boot parameter of the Linux Kernel.

Edit the grub configuration file:

nano /etc/default/grub

search fole the line that starts with GRUB_CMDLINE_LINUX and add rootflags=uquota,gquota to the commandline parameters so that the resulting line looks like this:


GRUB_CMDLINE_LINUX=" vconsole.font=latarcyrheb-sun16 crashkernel=auto vconsole.keymap=us rhgb quiet rootflags=uquota,gquota"

and apply the changes by running the following command.

cp /boot/grub2/grub.cfg /boot/grub2/grub.cfg_bak
grub2-mkconfig -o /boot/grub2/grub.cfg

and reboot the server.


Now check if quota is enabled:

mount | grep ' / '

[root@server1 ~]# mount | grep ' / '
/dev/mapper/centos-root on / type xfs (rw,relatime,attr2,inode64,usrquota,grpquota)
[root@server1 ~]#

When quota is active, we can see "usrquota,grpquota" in the mount option list.

Enabling quota on a separate /var partition

If you have a separate /var partition, then edit /etc/fstab and add ,uquota,gquota to the / partition (/dev/mapper/centos-var):

nano /etc/fstab

# /etc/fstab
# Created by anaconda on Sun Sep 21 16:33:45 2014
# Accessible filesystems, by reference, are maintained under '/dev/disk'
# See man pages fstab(5), findfs(8), mount(8) and/or blkid(8) for more info
/dev/mapper/centos-root /                       xfs     defaults        1 1
/dev/mapper/centos-var /var                     xfs     defaults,uquota,gquota        1 2
UUID=9ac06939-7e43-4efd-957a-486775edd7b4 /boot                   xfs     defaults        1 3
/dev/mapper/centos-swap swap                    swap    defaults        0 0


Then run

mount -o remount /var

quotacheck -avugm
quotaon -avug

to enable quota.


8 Synchronize The System Clock

It is a good idea to synchronize the system clock with an NTP (network time protocol) server over the Internet. Simply run

yum -y install ntp

and your system time will always be in sync.


9 Install MariaDB

We will install MariaDB-server and client as follows:

yum -y install mariadb mariadb-server

We want the Mariadb service to run on and after boot, and start the service as:

systemctl enable mariadb.service
systemctl start mariadb.service

Set passwords for the MySQL root account:


[root@server1 ~]# mysql_secure_installation
/usr/bin/mysql_secure_installation: line 379: find_mysql_client: command not found


In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none): <--ENTER
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n]
New password: <--yourmariadbpassword
Re-enter new password: <--yourmariadbpassword
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n]
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n]
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n]
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n]
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!
[root@server1 ~]#

10 Install Dovecot

Dovecot can be installed as follows:

yum -y install dovecot dovecot-pigeonhole dovecot-mysql

Create a empty dovecot-sql.conf file and symlink:

touch /etc/dovecot/dovecot-sql.conf
ln -s /etc/dovecot/dovecot-sql.conf /etc/dovecot-sql.conf

Now create the system startup links and start Dovecot:

systemctl enable dovecot.service
systemctl start dovecot.service


11 Install Postfix

Postfix can be installed as follows:

yum -y install postfix

Then turn off Sendmail and start Postfix:

systemctl enable mariadb.service
systemctl start mariadb.service
systemctl stop sendmail.service
systemctl disable sendmail.service
systemctl enable postfix.service
systemctl restart postfix.service


12 Install Getmail

Getmail can be installed as follows:

yum -y install getmail


13 Install Amavisd-new, SpamAssassin, And ClamAV

To install amavisd-new, spamassassin and clamav, run the following command:

yum -y install amavisd-new spamassassin clamav clamd clamav-update unzip bzip2 unrar perl-DBD-mysql

Edit the freshclam configuration file /etc/freshclam.conf

nano /etc/freshclam.conf

and comment out the line "Example"

# Example

Then we start freshclam, amavisd, and clamd.amavisd:

systemctl enable amavisd.service


14 Install Nginx, PHP5 (PHP-FPM), And Fcgiwrap

Nginx is available as a package for CentOS 7.0 (from EPEL) which we can install as follows:

yum -y install nginx

If Apache2 is already installed on the system, stop it now...

systemctl stop httpd.service

... and remove Apache's system startup links:

systemctl disable httpd.service

Then we create the system startup links for nginx and start it:

systemctl enable nginx.service
systemctl start nginx.service

(If both Apache2 and nginx are installed, the ISPConfig 3 installer will ask you which one you want to use - answer nginx in this case. If only one of these both is installed, ISPConfig will do the necessary configuration automatically.)

We can make PHP5 work in nginx through PHP-FPM (PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites). We can install php-fpm together with php-cli and some PHP5 modules like php-mysql which you need if you want to use MySQL from your PHP scripts as follows:

yum -y install php-fpm php-cli php-mysql php-gd php-imap php-ldap php-odbc php-pear php-xml php-xmlrpc php-pecl-apc php-magickwand php-mbstring php-mcrypt php-mssql php-snmp php-soap php-tidy

Next we open /etc/php.ini...

nano /etc/php.ini

... and change the error reporting (so that notices aren't shown any longer):

;error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
error_reporting = E_ALL & ~E_NOTICE

Also set cgi.fix_pathinfo=0:

nano /etc/php.ini

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts

(Please read to find out why you should do this.)

In addition to that, in order to avoid errors like

[08-Aug-2011 18:07:08] PHP Warning: phpinfo(): It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'Europe/Berlin' for 'CEST/2.0/DST' instead in /usr/share/nginx/html/info.php on line 2

... in /var/log/php-fpm/www-error.log when you call a PHP script in your browser, you should set date.timezone in /etc/php.ini:

; Defines the default timezone used by the date functions
date.timezone = "Europe/Berlin"

Next create the system startup links for php-fpm and start it:

systemctl enable php-fpm
systemctl restart php-fpm

PHP-FPM is a daemon process (with the init script /etc/init.d/php-fpm) that runs a FastCGI server on port 9000.

To get CGI support in nginx, we install Fcgiwrap.

Fcgiwrap is a CGI wrapper that should work also for complex CGI scripts and can be used for shared hosting environments because it allows each vhost to use its own cgi-bin directory.

As there's no fcgiwrap package for CentOS 7.0, we must build it ourselves. First we install some prerequisites:

yum -y install fcgi-devel

Now we can build fcgiwrap as follows:

cd /usr/local/src/
git clone git://
cd fcgiwrap
autoreconf -i
make install

This installs fcgiwrap to /usr/local/sbin/fcgiwrap.

Next we install the spawn-fcgi package which allows us to run fcgiwrap as a daemon:

yum -y install spawn-fcgi

Open /etc/sysconfig/spawn-fcgi...

nano /etc/sysconfig/spawn-fcgi

... and modify the file as follows:

# You must set some working options before the "spawn-fcgi" service will work.
# If SOCKET points to a file, then this file is cleaned up by the init script.
# See spawn-fcgi(1) for all possible options.
# Example :
#OPTIONS="-u apache -g apache -s $SOCKET -S -M 0600 -C 32 -F 1 -P /var/run/ -- /usr/bin/php-cgi"


Now add the user nginx to the group apache:

usermod -a -G apache nginx

Create the system startup links for spawn-fcgi...

chkconfig spawn-fcgi on

... and start it as follows:

systemctl start spawn-fcgi

You should now find the fcgiwrap socket in /var/run/fcgiwrap.socket, owned by the user and group apache (some scripts, e.g. Mailman, expect to be run by the user/group apache, that's why we don't run spawn-fcgi as user/group nginx, but instead add nginx to the apache group).


14.1 Additional PHP Versions

Starting with the ISPConfig 3.0.5, it is possible to have multiple PHP versions on one server (selectable through ISPConfig) which can be run through FastCGI and PHP-FPM. The procedure of building additional PHP versions on CentOS is described in this tutorial: How To Use Multiple PHP Versions (PHP-FPM & FastCGI) With ISPConfig 3 (CentOS 6.3)


Share this page:

Suggested articles

33 Comment(s)

Add comment


From: MTKBillH


GREAT Instructions, Thank you. It was a big help for someone that is extremely new at this. I have 1 suggestion and 1 correction I would like to recomend for #18.

For the BIND install command, I would like to suggest to run the chroot version from the start as that will set up a jailed environment for BIND initially rather then making the change later.

# yum -y install bind-chroot bind-utils

The second item is a typo in the named.conf internal file information. On line 21 you have file "data/"; it is missing a / before the data directory. It should be file "/data/";. 

Again, thank you.

Bill.. .. .

From: DirtyTodd

Me too


I have fourth Gen i5 CPU and unable to install CentOS on my System any solutions it gives error unsupported hardware.

Any Solution to it







Nice instruction. One thing to note:

Choose the mysql-password wisely. The ISPConfig Installation script doesnt detect/convert special characters. If you use eg ", the install script runs wild and it apparently breaks the later ISPConfig installation.

From: Darksin

Hi, thanks for really great tutorial but I have problem with phpMyAdmin. I can't access..

Here is log from /var/log/php-fpm/www.error.log :

PHP Fatal error:  Call to undefined function __() in /usr/share/phpMyAdmin/libraries/core.lib.php on line 242

I set chown 755 on directory (/etc/phpMyAdmin) but it doesn't work.

When i try install server on virtualbox this problem appear too...

Can anybody help me ?

From: Jon S

Got stuck at the end of Number 4, it tried all the mirrors and failed

yum -y install net-tools NetworkManager-tuiError downloading packages:  1:NetworkManager-tui- [Errno 256] No more mirrors to try.  1:NetworkManager-glib- [Errno 256] No more mirrors to try.  1:NetworkManager- [Errno 256] No more mirrors to try.

From: Yado


after install all my service like webserver ftp ...are offline

Web-Server: Online FTP-Server: Online SMTP-Server: Online POP3-Server: Offline IMAP-Server: Offline DNS-Server: Online mySQL-Server: Online

how to solve this?



From: Yado


now is ok maybe the service start after some second/minutes...



From: Yado


howto set file2ban for sent admin mail when system is under attack?



From: Razzbee

There is a little bug here, the roundcubmail configuration installer path was not working for me : Insetad of :


I used :

http://serverIp:8081/webmail/installer or http://serverIp:8081/squirrelmail/installer

Hope It helps Someone

From: Tuyre

Where was phpmyadmin installed?


I'm getting a 404 error when trying to manage a new database I created.

Are there seperate instructions for installing phpmyadmin?

From: till

PHPmyadmin is on:


From: Myungjin


What is roundcubemail logging ID/PW?

From: till

The email address and password of the mail account that you created in ISPConfig.

From: nospoon

I've gone through most of the steps without problems, however when trying to access domain on port 8080 or 8081 I get ERR_CONNECTION_REFUSED

From: Carl

These instructions worked fairly well, but for some reason I'm not getting the [ok] or [failed] message when restarting services.

Also when attempting to finish the roundcube installation I'm getting a 404 when I try to access http://my.ip.address:8081/roundcubemail/installer

I can access the ispconfig login just fine and I get a nice nginx test page when I just use my ip address for a url.

From: Ali

My IP is not resolving any of the above, but the install was successful... UGH.

From: brody

DO NOT INSTALL ON VPS   ( yum -y install net-tools NetworkManager-tui )

From: denuxer

How do i Update the PHP version do to the High risk vulnerabilities 

From: till

The PHP packages are from CentOS, you update the with the usual yum update command.

From: denuxer

i try yum update still my version is 5.4 i want to upgrade to 5.5 or 5.6

with yum update php wont work to... 

[root@htp ~]# yum update php

Loaded plugins: fastestmirror, priorities

Loading mirror speeds from cached hostfile

 * base:

 * epel:

 * extras:

 * updates:

192 packages excluded due to repository priority protections

No packages marked for update

[root@htp ~]# yum update php

Loaded plugins: fastestmirror, priorities

Loading mirror speeds from cached hostfile

 * base:

 * epel:

 * extras:

 * updates:

192 packages excluded due to repository priority protections

No packages marked for update


From: dongbak

 Thank you. I received a big help by your guidance. I have completed the installation of Ispconfig3 on the Centos7. I am now upgrading php 5.4.16 to php 5.5 +. I hope that your guidance is upgraded. Thank you.


From: levi

I was interested in this until the author recommended disabling SELinux because it's easier than making it work...

From: till

As you might know, the package builders from CentOS miss to publish SELinux Rule sets for most of their packages in the main and epel repository, that's why most CentOS software will stop working with SELinux on. So that's not specific to this setup and not related to the use of ISPConfig. It would be nice off course to use SELinux, so feel free to contribute a rule set.

From: no0ne

If using this setup, and you're messing around with permissions for nginx, you'd do well to backup your current set of permissions just incase:

find /var/www/*/web/ -printf 'chmod %#m "%p"\n' > /root/permission-backup_`date +%s`.sh ; find /var/www/*/web/ -printf 'chown %u:%g "%p"\n' > /root/owner-backup_`date +%s`.sh

From: Maghin

Are you serious ?

Configuring a firewall means to disable it ?

From: till

Sure. I guess you never used ispconfig, otherwise you would know that it ships with its own firewall engine so the centos firewall has to be disabled as it collides with the ispconfig firewall.

From: Howard

Is it possible to use VSFTPD instead of PureFTPD and if so what is needed to do it?  Can I just replace the instructions for PureFTPD and use VSFTPD and configure that?


From: till

No, that's not possible as vsftpd does not support virtual users in MySQL.

From: Bogdan


I couldn't install roundcube using the intaller link. (The one in the screenshot works !)

It should be : instead of

From: Bogdan

I had many errors like : connect to /var/run/clamd.amavisd/clamd.sock failed, attempt #1: Can't connect to a UNIX socket /var/run/clamd.amavisd/clamd.sock

In your other tutorial with Apache instead of nginx, there are aditional packages installed for clam, at step 13 :

yum  install amavisd-new spamassassin clamav-server clamav-data clamav-update clamav-filesystem clamav clamav-scanner-systemd clamav-devel clamav-lib clamav-server-systemd unzip bzip2 perl-DBD-mysql

Also, ISPConfig created /etc/amavisd.conf, but amavis uses /etc/amavisd/amavisd.conf.

So rename the conf file and create a symlink to the file created by ispconfig :

ln -s /etc/amavisd.conf /etc/amavisd/amavisd.conf

I've used CentOS 7.2

From: till

The tutorial on this page tutorial is for CentOS 7.0 only and not 7.2. The perfect server tutorial for CentOS 7.2 is here:

From: Secure

Disabled selinux, Disabled Firewall...What?????

From: Thomas

ISPConfig ships with it's own firewall, so the CentOS firewall has to be disabled as you can not run two firewalls at the same time and regarding SELinux, the setup won't work when it is on, but feel free to write a rule set and post it if you want to use SELinux.