CentOS 7 – Setting up a web server using Apache-MySQL-PHP

How to set a static IP address on Windows Server 2019

One of the common services that a Linux server offers is being a web server, to give its user the capacity to host their web content in a secure, fast, and reliable location, browsable from all over the world. In this section, we are going to show you how to set up a reliable web server on a CentOS 7 server with some security modules that will secure the website, and we will do an implementation of a
Content Management System ( CMS): Joomla.

Our web server will host dynamic websites and web applications. So we will install a LAMP (Stack) server, represent a Linux operating system with the Apache web server, where the site data will be stored in MySQL databases (using MariaDB, which is a community-developed fork of the MySQL relational database management system intended to remain free under the GNU GPL), and dynamic content processed by PHP.

We will start with the installation of the Apache web server, which is the most popular web server in the world:

$ sudo yum install httpd

By the end of the command, the Apache web server is successfully installed. We can start it using the command systemctl:

$ sudo systemctl start httpd.service

Before testing the service, we need to make sure that the server firewall allows web access. So, we need to open the ports that Apache is serving from, HTTP (80) and HTTPS (443):

$ sudo firewall-cmd --permanent --add-service=http
$ sudo firewall-cmd --permanent --add-service=https
$ sudo firewall-cmd --reload

We can now test the web server by typing in any other machine web browser inside the same network IP address of the server ( http://Server_IP_Address). We should see something like this:

After making sure that the service is working fine, we need to add it to the system startup services:

$ sudo systemctl enable httpd.service

Now we will set up two virtual hosts on Apache to show Apache’s capacity to support multiple websites.

For the next part, we will make a number of changes to the Apache configuration file, so we will create a backup file:

$ sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.backup

Apache has the capacity to separate its functionality and components into units that can be customized and configured independently. These units are called
virtual hosts. Virtual hosts allow us to host multiple domains. Each configured domain will direct the visitors to a specific folder specified to the website, which holds its information. This technique is extendable as long as the server can handle the traffic attracted by the websites stored inside it.

First, we need to make the folders where we are going to store our websites. The directory /var/www/ is our web server root directory:

$ sudo mkdir –p /var/www/packt.co.uk/home
$ sudo mkdir –p /var/www/packt2.co.uk/home

Then we grant these folders permission to be accessible by changing the ownership from the root (the user who just created them) to the $USER (the user that is currently logged in):

$ sudo chown –R $USER:$USER /var/www/packt.co.uk/home
$ sudo chown –R $USER:$USER /var/www/packt2.co.uk/home

To fully test the virtual hosts, we need to create an example HTML page to be opened at the client web browser:

$ nano /var/www/packt.co.uk/home/index.html

Then we add some HTML code to populate the page:

    <title>Packt Home Page</title>
    <h1>Welcome to the home page of the Packt Publishing 1st example web server </h1>

Similarly, for the second host, we need to create the same file with different content to tell the difference:

$ nano /var/www/packt2.co.uk/home/index.html

And then we put in the following HTML code:

    <title>Packt2 Home Page</title>
    <h1>Welcome to the home page of the Packt Publishing 2nd example web server </h1>

Now we need to create the virtual host files in the Apache configuration folder. We start by creating the folders where we need to put our files:

$ sudo mkdir /etc/httpd/sites-available
$ sudo mkdir /etc/httpd/sites-enabled

Then we need to tell the Apache service to use the configuration provided at the sites-enabled directory by editing the Apache main configuration file. This configuration can also be obtained as the configuration directory /etc/httpd/conf.d.

$ sudo nano /etc/httpd/conf/httpd.conf.

Then we add the following line to the end of the file:

IncludeOptional sites-enabled/*.conf

We save the file, then we move to the virtual host file creation in the folder sites-available. The file should always end with .conf so the Apache service can use it:

$ sudo nano /etc/httpd/sites-available/packt.co.uk.conf

Then we put the following configuration inside it:

<VirtualHost *:80>

    ServerName www.packt.co.uk
    ServerAlias packt.co.uk
    DocumentRoot /var/www/packt.co.uk/home
    ErrorLog /var/log/httpd/packt.co.uk_error.log
    CustomLog /var/log/httpd/packt.co.uk_requests.log combined


We save the file, and then do the same thing for the second virtual host:

$ sudo nano /etc/httpd/sites-available/packt2.co.uk.conf

And we put the following commands inside it:

<VirtualHost *:80>

    ServerName www.packt2.co.uk
    ServerAlias packt2.co.uk
    DocumentRoot /var/www/packt2.co.uk/home
    ErrorLog /var/log/httpd/packt2.co.uk_error.log
    CustomLog /var/log/httpd/packt2.co.uk_requests.log combined


After configuring both sites, we can now activate the Virtual Hosts to be usable:

$ sudo ln -s /etc/httpd/sites-available/packt.co.uk.conf /etc/httpd/sites-enabled/packt.co.uk.conf
$ sudo ln -s /etc/httpd/sites-available/packt2.co.uk.conf /etc/httpd/sites-enabled/packt2.co.uk.conf

To make sure that all the configurations we have done will be effected, we need to restart the Apache service by using either of these commands:

$ sudo apachectl restart
$ sudo systemctl restart httpd.service


If we ever get any error related to our server host name, try to use this command to change it and get rid of the error:

$ sudo hostnamectl set-hostname --static packt.co.uk

In our case, those domains are not public and they are not defined by any DNS server. So we can either add them to our local DNS server or we can just add them to the /etc/hosts file in our client machine (the machine where we are going to open the web browser). This step is only to do the test. Usually we should define them with the DNS server of the ISP or at the local DNS server:

$ sudo nano /etc/hosts

Then we add the two lines that associate our web server IP address to the two domains that we have created:

Server_IP_Address    packt.co.uk
Server_IP_Address    packt2.co.uk

Then we go to the client web browser and we type the domain in the address bar:


We should see the page associated with the first domain. We do the same thing for the second domain. If the test is valid, we confirm that our virtual hosts have been created properly.

Now we can move to secure Apache against one of the most common attacks that is affect the world’s websites. A brute-force attack or Distributed Denial of Service ( DDoS) attack is a kind of attack that sends multiple requests to the same web server to overload it and make it unreachable. Now we are going to set up modules that help secure our web server from the kinds of attack. Mod_Security and Mod_evasive are the basic modules that will help detect and prevent intrusions, and help reinforce the web server protection against brute-force or DDoS attacks. First, we need to install the modules using the package manager. We require that the system already has the EPEL repository installed:

$ sudo yum install mod_security mod_evasive

So to verify that the installation is complete we need to see whether there are two files that have been created in the /etc/httpd/conf.d/ folder:

$ sudo ls /etc/httpd/conf.d/mod_*

To make sure that Apache loads these two modules when it starts, we need to add some configuration options to the two configuration files, which have been created after the installation:

$ sudo nano /etc/httpd/conf.d/mod_evasive.conf
$ sudo nano /etc/httpd/conf.d/mod_security.conf

And we add the following lines respectively or we make sure that they are uncommented:

LoadModule evasive20_module modules/mod_evasive24.so
LoadModule security2_module modules/mod_security2.so

Now we can restart Apache so the configuration can take effect:

$ sudo service httpd restart

We start by configuring the Mod_Security module. So we need to set up a Core Rule Set ( CRS). We will download a free CRS (OWASP) to have it configured for our web server. We need to create a directory to put the rules inside before downloading its package:

$ sudo mkdir /etc/httpd/crs-tecmint
$ cd /etc/httpd/crs-tecmint
$ sudo wget https://github.com/SpiderLabs/owasp-modsecurity-crs/tarball/master

After that we can extract the package there and we can change its name to an appropriate one:

$ sudo tar –xzvf master
$ sudo mv SpiderLabs-owasp-modsecurity-crs-c63affc/ owasp-modsecurity-crs

Now we can start configuring the Mod_Security module. We need to copy the sample file configuration into another file without the . example extension:

$ cd owasp-modsecurity-crs
$ sudo cp modsecurity_crs_10_setup.conf.example modsecurity_crs_10_setup.conf

Then tell Apache to use this module by inserting the following line into the Apache main configuration file:

$ sudo nano /etc/httpd/conf/httpd.conf
<IfModule security2_module>
    Include crs-tecmint/owasp-modsecurity-crs/modsecurity_crs_10_setup.conf
    Include crs-tecmint/owasp-modsecurity-crs/base_rules/*.conf

Now we need to create a configuration file in the /etc/httpd/modsecurity.d/ directory to make it easier to upgrade the CRSs if there are newer versions:

$ sudo nano /etc/httpd/modsecurity.d/tecmint.conf

After creating the new file, we need to add the following line and save the file:

<IfModule mod_security2.c>
  SecRuleEngine On
  SecRequestBodyAccess On
  SecResponseBodyAccess On 
  SecResponseBodyMimeType text/plain text/html text/xml application/octet-stream 
  SecDataDir /tmp

With this step we can say that the Mod_Security module is successfully installed and configured. We can now move to the next module, Mod_Evasive. To configure this module, we need to make sure that some lines are not commented in the main configuration file:

$ sudo nano /etc/httpd/conf.d/mod_evasive.conf

And then check the IfModule options are successfully set:

<IfModule mod_evasive24.c>
    DOSHashTableSize    3097
    DOSPageCount        2
    DOSSiteCount        50
    DOSPageInterval     1
    DOSSiteInterval     1
    DOSBlockingPeriod   10

Let’s go through the previous code in some detail:

  • DOSHashTableSize: This option specifies the size of the hash table used to keep track of the IP’s activities
  • DOSPageCount: The legitimate number of identical requests to one resource from one IP address
  • DOSSiteCount: The same as the DOSPageCount, but for all the requests that can be made
  • DOSBlockingPeriod: The blacklisting period for an IP that excludes the options on top

Those numbers are an example of configuration. We can change them as per our need.

An extra option that can be useful is DOSSystemCommand, which helps to run some script that can block IP addresses. To do so we need to add it to the configuration file.

DOSSystemCommand "sudo /etc/httpd/scripts/ban_ip.sh %s".

And we need to create the script at an appropriate location:

$ sudo nano /etc/httpd/scripts/ban_ip.sh

And we should add the following code inside it:

echo "$IPTABLES -D INPUT -s $IP -j DROP" | at now + 2 hours
rm -f "$MOD_EVASIVE_LOGDIR"/dos-"$IP"

This script requires some system modifications to run properly. Let’s make it executable:

$ sudo chmod +x /etc/httpd/scripts/ban_ip.sh

We need to add a line to the Sudoers rule file:

$ sudo nano /etc/Sudoers
apache ALL=NOPASSWD: /usr/local/bin/scripts/ban_ip.sh
Defaults:apache !requiretty

For security reasons, editing the file directly may be harmful. We recommend using the following command:

$ sudo visudo

Second, this script works with iptables so we need to deactivate Firewalld and install and activate iptables:

$ sudo yum update && yum install iptables-services
$ sudo systemctl enable iptables
$ sudo systemctl start iptables
$ sudo systemctl status iptables

Then apply the new configuration we need to restart the Apache service:

$ sudo systemctl restart httpd

Finally, our web server is well secured and configured.

As a small tip, the Apache server by default shows what operating system and version it has been running on. Sometimes it shows what modules are installed. That information can be very valuable for attackers to use as a vulnerability, so we need to disable the display of that information:

$ sudo nano /etc/httpd/conf/httpd.conf

And then we change the following two lines to look like this:

ServerSignature Off
ServerTokens Prod

We can now move to database installation. The database in a server is essential for the execution of a dynamic website to be used as a medium to store its data. Usually, on old Linux versions, we install MySQL as our default database server but recently most Linux distros have migrated to the MariaDB database server. To do so, we need to use the package manager to install it:

$ sudo yum install mariadb-server mariadb

We are going to install some modules that are not available in the default repository. So we need to install the EPEL repository to make sure that we are covered for this part:

$ sudo yum install epel-release

Then we start the service and enable it for the next startup:

$ sudo systemctl start mariadb
$ sudo systemctl enable mariadb.service

To have a well-secured database server, we need to use the MariaDB secure installation command. This command is very useful to customize the level of security of the database server with a variety of options:

$ sudo mysql_secure_installation


We should make sure to specify a powerful root password for the database during the execution of the command.

To make sure that our database server is working correctly we can just run the CLI interface and run some basic SQL commands:

$ sudo mysql -u root -p

We type the password already set during the secure installation and we will have the MariaDB CLI. To quit it just type quit.

In order not to type the password each time, we can write the password in a file located in our home directory ~/.my.cnf and add the following line:


We can now move to the PHP5 installation. In the future, we will add phpmyadmin, which is a program that allows the management of the MariaDB database via a graphical interface accessible via the web browser. First, we start by installing PHP5 and the library that supports MySQL for PHP:

$ sudo yum install php php-mysql

We can edit /etc/php/php.ini to configure where to put error messages, the maximum size to upload a file to the website (very useful for dynamic websites that handle files), and so on.

We can do some minor configuration to make PHP more secure. First, we can remove the information and errors message and log them to a log file. Then turn off remote code execution. Also, if we are not in need of a file upload in the website, we can disable it. We need to use a safe SQL mode. Finally, we disable dangerous PGP functions:

$ sudo nano /etc/php.d/secutity.ini

Then, change the following lines:





disable_functions =exec,passthru,shell_exec,system,proc_open,popen,curl_exec,curl_multi_exec,parse_ini_file,show_source

To protect PHP from known and unknown flows, we consider installing the Suhosin advanced protection system:

$ sudo yum install php-devel
$ sudo cd /usr/local 
$ sudo wget –c https://download.suhosin.org/suhosin-0.9.38.tar.gz
$ sudo tar -xzvf suhosin-0.9.38.tar.gz
$ sudo cd suhosin-0.9.38
$ sudo phpize
$ sudo ./configure
$ sudo make 
$ sudo make install

Now we configure it so Apache starts using it:

$ sudo echo 'extension=suhosin.so' > /etc/php.d/suhosin.ini

Then we restart Apache:

$ sudo systemctl restart httpd

Now, we move to the installation of the packages required for the phpmyadmin installation:

$ sudo yum install php-gd php-pear php-mbstring 

After installing them, we install the phpmyadmin package:

$ sudo yum install phpMyAdmin

We need to do a little configuration to enable outside access to the interface of phpmyadmin other than from the server itself. We need to edit its configuration file:

$ sudo nano /etc/httpd/conf.d/phpMyAdmin.conf

Then we need to comment the old configuration:

#<Directory /usr/share/phpMyAdmin/>
#   <IfModule mod_authz_core.c>
#     # Apache 2.4
#     <RequireAny>
#       Require ip
#       Require ip ::1
#     </RequireAny>
#   </IfModule>
#   <IfModule !mod_authz_core.c>
#     # Apache 2.2
#     Order Deny,Allow
#     Deny from All
#     Allow from
#     Allow from ::1
#   </IfModule>

And add the new configuration that grants access:

<Directory /usr/share/phpMyAdmin/>
        Options none
        AllowOverride Limit
        Require all granted

Finally, we need to change the authentication from cookie to http:

$ sudo nano /etc/phpMyAdmin/config.inc.php

And change this line to look like this:

$cfg['Servers'][$i]['auth_type']     = 'http';

So that the change can take effect, we need to restart Apache:

$ sudo systemctl restart httpd.service

To test whether it worked, we only need to type in any web browser located on the same network as the web server http://Server_IP_Addr
ess/phpmyadmin. Then we need to provide the database root user and its password to log in. We can secure phpMyAdmin by editing its configuration file such as restricting the source IP address that can access the service.

To be able to install a
Content Management System ( CMS) such as WordPress, Joomla, or Drupal, we need to install some PHP modules:

$ sudo yum -y install php-gd php-ldap php-odbc php-pear php-xml php-xmlrpc php-mbstring php-snmp php-soap curl curl-devel

After installing those modules, we can proceed with our CMS installation. In our case, we will be installing Joomla. First, we need to go to the Joomla website and download the latest version into /var/www or any Virtual Host folder. Using Wget we will download the Joomla package:

$ cd /var/www/packt2.co.uk/home/
$ get -c https://github.com/joomla/joomla-cms/releases/download/3.4.3/Joomla_3.4.3-Stable-Full_Package.zip

Then we need to extract the package using the unzip command:

$ unzip Joomla_3.4.3-Stable-Full_Package.zip


We need to make sure that the folder where we are going to extract the package is empty to have a safe installation with no errors.

After that we can go and open, in any client web browser, the domain where we extracted the CMS package:


Then we need to follow the steps of the installation provided on the website. Here is a brief description of what we should provide to finish the installation:

  1. We need to provide the website name and some of the site administrator information (mail, name, password):
  2. In the database part, we need to provide which database we are using ( MySQL), then the server host name ( localhost), and the user and password of the database ( root), and finally a name of the database in which to store the site information:
  3. If needed, we can enable the FTP server by providing the FTP user and its password, and verify the service to check whether it is running.
  4. Then we will have an overview where we can check the configuration that we have entered and we can have it sent to the administrator via e-mail.
  5. Finally, we click install to have the website installed and configured.

    As this screenshot shows, we can determine the status of the pre-requirement of our CMS:

  6. The installation site will remind us to remove the installation folder since it can present a vulnerability to the website. So to reinforce the security we need to remove it manually:
    $ sudo rm -rf installation/
  7. Then we need to copy the configuration provided on the site and put it inside a file that we create in the site folder and then save it:
    $ sudo nano configuration.php

We can access the site and navigate to it or we can open the administration panel to make some tweaks to the site or manage the settings:


Now we can say that we have installed and secured our web server and it is ready for use.

Comments are closed.