How to install Nginx using PHP and MySQL (LEMP Stack) on CentOS 7.6

How to install Nginx using PHP and MySQL (LEMP Stack) on CentOS 7.6

This tutorial explains how to install Nginx on a CentOS 7 server with PHP support (via PHP-FPM) and MySQL (MariaDB) support.

What is LEMP?

Nginx (Pronounced “engine x”) is a free and open source high-performance HTTP server. Nginx is known for its stability, rich feature set, simple configuration and low resource consumption.

LEMP prerequisites

In this tutorial, I will use the host name with the IP address These settings may vary depending on you, so you must replace them where appropriate.

In this tutorial, I will use the nano editor to edit the configuration file. Nano can be installed this way.

yum -y install nano

I recommend installing a firewall. If firewalld has not been installed and you want to use a firewall, use the following command to install it:

yum -y install firewalld

Start the firewall and enable it to start at boot.

systemctl start firewalld.servicesystemctl enable firewalld.service

Next, open your SSH port to ensure that you will be able to connect to the server via SSH.

firewall-cmd --permanent --zone=public --add-service=sshfirewall-cmd --reload

Enable other CentOS databases

The latest Nginx is not available from the official CentOS repository, so we include the repository of the Nginx project for installation:

nano /etc/yum.repos.d/nginx.repo
name=nginx repo

Install MySQL (MariaDB)

First, we install MariaDB as an alternative to MySQL. MariaDB is a free branch of MySQL. Run the following command on the shell to install MariaDB database server:

yum -y install mariadb mariadb-server net-tools

Then, we create a system startup link for MariaDB (so that it starts automatically when the system starts) and start the MariaDB server:

systemctl enable mariadb.servicesystemctl start mariadb.service

Now check if the network connection is enabled. Please note that the MraiDB service is named mysql because it is a compatible database server. run

netstat -tap | grep mysql

It should display the following:

[[email protected] ~]# netstat -tap | grep mysqltcp 0 0* LISTEN 19842/mysqld 



Set a password for user root (otherwise, anyone can access your MySQL database!):

[[email protected] ~]# 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 currentpassword for the root user. If you've just installed MariaDB, andyou 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):OK, successfully used password, moving on...
Setting the root password ensures that nobody can log into the MariaDBroot user without the proper authorisation.
Set root password? [Y/n] <-- ENTERNew password: <-- yourrootsqlpasswordRe-enter new password: <-- yourrootsqlpasswordPassword updated successfully!Reloading privilege tables..... Success!
By default, a MariaDB installation has an anonymous user, allowing anyoneto log into MariaDB without having to have a user account created forthem. This is intended only for testing, and to make the installationgo a bit smoother. You should remove them before moving into aproduction environment.
Remove anonymous users? [Y/n] <-- ENTER... Success!
Normally, root should only be allowed to connect from 'localhost'. Thisensures that someone cannot guess at the root password from the network.
Disallow root login remotely? [Y/n] <-- ENTER... Success!
By default, MariaDB comes with a database named 'test' that anyone canaccess. This is also intended only for testing, and should be removedbefore moving into a production environment.
Remove test database and access to it? [Y/n] <-- ENTER- Dropping test database...... Success!- Removing privileges on test database...... Success!
Reloading the privilege tables will ensure that all changes made so farwill take effect immediately.
Reload privilege tables now? [Y/n] <-- ENTER... Success!
Cleaning up...
All done! If you've completed all of the above steps, your MariaDBinstallation should now be secure.
Thanks for using MariaDB![[email protected] ~]#

[[email protected] ~]#mysql_secure_installation

Install Nginx

Nginx is a package of, we can install it like this:

yum -y install nginx

Then, we create a system startup link for nginx and start it:

systemctl enable nginx.servicesystemctl start nginx.service

You may receive an error message indicating that port 80 has been used. The error message will be as follows:

[[email protected] ~]# service nginx startStarting nginx: nginx: [emerg] bind() to failed (98: Address already in use)nginx: [emerg] bind() to failed (98: Address already in use)nginx: [emerg] bind() to failed (98: Address already in use)nginx: [emerg] bind() to failed (98: Address already in use)nginx: [emerg] bind() to failed (98: Address already in use)nginx: [emerg] still could not bind()                                                           [FAILED][[email protected] ~]#

This means that another web server (probably Apache) is already running on the server. Stop the Apache service, and then start the service for NGINX:

systemctl stop httpd.serviceyum remove httpdsystemctl disable httpd.service

Then try to start Nginx again.

systemctl start nginx.service

Open HTTP and HTTPS ports in the firewall

firewall-cmd --permanent --zone=public --add-service=httpfirewall-cmd --permanent --zone=public --add-service=httpsfirewall-cmd --reload

The result output on the Shell is as follows:

[[email protected] ~]# firewall-cmd --permanent --zone=public --add-service=httpsuccess[[email protected] ~]# firewall-cmd --permanent --zone=public --add-service=httpssuccess[[email protected] ~]# firewall-cmd --reloadsuccess[[email protected] ~]#

Enter the IP address or host name of the web server in your browser (for example, you should see the Nginx welcome page:


Install PHP

We can make PHP 5 work with Nginx in the following ways PHP-FPM (FastCGI process manager). PHP-FPM is an alternative implementation of PHP FastCGI and has some other features that can be used on sites of all sizes, especially busy sites. We can install php-fpm with php-cli and some PHP5 modules (such as php-mysql). If you want to use MySQL from a PHP script, you need to use them as follows:

yum -y install php-fpm php-cli php-mysql php-gd php-ldap php-odbc php-pdo php-pecl-memcache php-pear php-mbstring php-xml php-xmlrpc php-mbstring php-snmp php-soap

APC is a free and open PHP opcode buffer for caching and optimizing PHP intermediate code. It is similar to other PHP opcode caches, such as eAccelerator and Xcache. It is strongly recommended to install one of them to speed up the speed of PHP pages.

I will install APC from PHP pecl repository. PECL requires the installation of Centos development tools to compile APC software packages.

yum -y install php-develyum -y groupinstall 'Development Tools'

And install APC:

pecl install apc
[[email protected] ~]# pecl install apcdownloading APC-3.1.13.tgz ...Starting to download APC-3.1.13.tgz (171,591 bytes).................done: 171,591 bytes55 source files, buildingrunning: phpizeConfiguring for:PHP Api Version: 20100412Zend Module Api No: 20100525Zend Extension Api No: 220100525Enable internal debugging in APC [no] : <-- ENTEREnable per request file info about files used from the APC cache [no] : <-- ENTEREnable spin locks (EXPERIMENTAL) [no] : <-- ENTEREnable memory protection (EXPERIMENTAL) [no] : <-- ENTEREnable pthread mutexes (default) [no] : <-- ENTEREnable pthread read/write locks (EXPERIMENTAL) [yes] : <-- ENTERbuilding in /var/tmp/pear-build-rootVrjsuq/APC-3.1.13......

Then open /etc/php.ini and 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 Find out why. )

And add the following line:


At the end of the /etc/php.ini file.

In addition, to avoid time zone errors

[28-June-2016 14:21:01] 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 the 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"

You can find the correct time zone of the system by running the following command:

Cat / etc / sysconfig / clock

[[email protected] nginx]# Cat / etc / sysconfig / clockZONE = "Europe / Berlin"[[email protected] nginx]#

Next, create a system startup link for php-fpm and start it:

systemctl enable php-fpm.servicesystemctl start php-fpm.service

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

Configure Nginx

The nginx configuration is located in /etc/nginx/nginx.conf that we now open:

nano /etc/nginx/nginx.conf

First (this is optional), you can increase the number of worker processes and set keepalive_timeout to a reasonable value:

worker_processes  4;
    keepalive_timeout  2;

The virtual host is defined in the server {} container in the /etc/nginx/conf.d directory. Let's modify the default virtual host (in /etc/nginx/conf.d/default.conf) as follows:

nano /etc/nginx/conf.d/default.conf
server {
    listen       80;
    server_name  localhost;

    #charset koi8-r;
    #access_log  /var/log/nginx/log/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm index.php;

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;

    # proxy the PHP scripts to Apache listening on
    #location ~ .php$ {
    #    proxy_pass;

    # pass the PHP scripts to FastCGI server listening on

    location ~ .php$ {
        root           /usr/share/nginx/html;
        try_files $uri =404;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;
	# deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    location ~ /.ht {
        deny  all;

The server name _; makes it the default comprehensive virtual host (of course, you can also specify the host name here, for example

In the location / section, I have added index.php to the index line. The root directory / usr / share / nginx / html; indicates that the document root directory is the directory / usr / share / nginx / html.

The important part of PHP is the location ~ .php $ {} section. Uncomment to enable it. Change the root line to the document root directory of the website (for example, root directory / usr / share / nginx / html;). Please note that I have added the line try_files $ uri = 404; to prevent zero-day attacks (see with,88845,page=3). Please make sure to change the fastcgi_param line to fastcgi_param SCRIPT_FILENAME $ document_root $ fastcgi_script_name; because otherwise, the PHP interpreter will not find the PHP script you call in the browser ($ document_root will be converted to / usr / share / nginx / html because of this Is the location we set as the document root directory).

PHP-FPM is listening on port 9000 at by default, so we tell Nginx to connect to via fastcgi_pass; You can also make PHP-FPM use Unix sockets-I will describe this in Chapter 7.

Now save the file and reload Nginx:

systemctl restart nginx.service

Now, create the following PHP file in the file root directory / usr / share / nginx / html:

nano /usr/share/nginx/html/info.php

Now, we call the file in the browser (for example

PHP information from our nginx server.

As you can see, PHP 5 is running and is running through FPM / FastCGI as shown in the server API line. If you scroll down, you will see all the modules enabled in PHP5, including the MySQL module:

The MySQL driver has been activated in PHP.

Make PHP-FPM use Unix sockets

By default, PHP-FPM is listening on port 9000 at You can also make PHP-FPM use Unix sockets to avoid TCP overhead. To do this, open /etc/php-fpm.d/www.conf ...

nano /etc/php-fpm.d/www.conf

... and make the listening line look like this:

;listen =
listen = /var/run/php-fpm/php5-fpm.sock

Then reload PHP-FPM: Advertising


systemctl restart php-fpm.service

Next, check your Nginx configuration and all virtual hosts, and change the fastcgi_pass line; to fastcgi_pass Unix: /tmp/php5-fpm.sock ;, for example like this:

vi /etc/nginx/conf.d/default.conf
    location ~ .php$ {
        root           /usr/share/nginx/html;
        try_files $uri =404;
        fastcgi_pass   unix:/var/run/php-fpm/php5-fpm.sock;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        include        fastcgi_params;

Finally, reload Nginx:

systemctl restart nginx.service

Download this CentOS 7 server as a virtual machine

This setting can be downloaded as a virtual machine in ova / ovf format (compatible with VMWare and Virtualbox) for use by howtoforge subscribers.

Virtual machine login details

  • The root password is: howtoforge
  • The password for the "Administrator" user is: howtoforge

Please change both passwords when logging in for the first time.

  • The IP address of the virtual machine is