Install Nginx, MariaDB, PHP (LEMP Stack) in Ubuntu 16.04 LTS

In our previous tutorial, we see how to install LAMP stack in Ubuntu 16.04 LTS server. In this tutorial, we will see how to install Nginx, MariaDB, PHP (LEMP stack) in Ubuntu 16.04 LTS. Like I mentioned in the previous tutorial, LEMP is the acronym of Linux, Engine-x, MariaDB/MySQL, PHP/Perl/Python.

For the purpose of this tutorial, I will be using the following test machine.

  • Operating System : Ubuntu 16.04 64bit LTS Server
  • IP Address : 192.168.1.102/24
  • Hostname : server.sysvn.net

Let us get started.

1. Install Nginx

Open the Terminal, and run the following command to install Nginx webserver:

sudo apt-get install nginx

After installing Nginx, check if Nginx service is running or not using command:

sudo systemctl status nginx

Sample output:

● nginx.service - A high performance web server and a reverse proxy server
 Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
 Active: active (running) since Fri 2016-06-03 16:42:22 IST; 5min ago
 Main PID: 1169 (nginx)
 CGroup: /system.slice/nginx.service
 ├─1169 nginx: master process /usr/sbin/nginx -g daemon on; master_process on
 └─1170 nginx: worker process 

Jun 03 16:42:22 server systemd[1]: Starting A high performance web server and a reverse proxy server...
Jun 03 16:42:22 server systemd[1]: nginx.service: Failed to read PID from file /run/nginx.pid: Invalid argument
Jun 03 16:42:22 server systemd[1]: Started A high performance web server and a reverse proxy server.

If you see an output like above, the Nginx service has been started.

In case it is not started yet, you can start it using command:

sudo systemctl start nginx

Let us go ahead and run Nginx test page.

To do so, open up your Web browser and navigate to http://localhost/ or http://IP-Address/.

You will see a page something like below.

If you see an output like above, congratulations! Nginx server is working!

2. Install MariaDB

MariaDB is the drop-in replacement of MySQL database server.

To install it, run:

sudo apt-get install mariadb-server

The version of MariaDB in the Ubuntu official repositories might be outdated. If you want to install a latest MariaDB, add the MariaDB official repository and install it as shown below.

First, add MariaDB repository and import the key as shown below.

sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386] http://mirror.fibergrid.in/mariadbrepo/10.1/ubuntu xenial main'

After adding the repository, run the following commands to install MariaDB.

sudo apt-get update
sudo apt-get install mariadb-server

Setup database administrative user (root) password

During MariaDB installation, It will not you to set password for the administrative user account (root).

If you try to setup password manually using command:

mysql_secure_installation

You can’t login set the password. You will see an error like below.

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
 SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

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): 
ERROR 1698 (28000): Access denied for user 'root'@'localhost'
Enter current password for root (enter for none):

To fix this problem, log in as MySQL database administrator using command:

sudo mysql -u root

After logging into the MySQL prompt, run the following commands one by one.

use mysql;
update user set plugin='' where User='root';
flush privileges;
\q

Now, you can set database administrative password using command:

mysql_secure_installation

Enter password password, and hit ENTER key to accept the default values.

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
 SERVERS IN PRODUCTION USE! PLEASE READ EACH STEP CAREFULLY!

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): # Press 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] # Press ENTER
New password: # Enter password
Re-enter new password: # Re-enter password
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] # Press ENTER
 ... 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] # Press ENTER
 ... 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] # Press ENTER
 - Dropping test database...
ERROR 1008 (HY000) at line 1: Can't drop database 'test'; database doesn't exist
 ... Failed! Not critical, keep moving...
 - 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] # Press ENTER
 ... Success!

Cleaning up...

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

That’s it. Password for the database administrative user account has been set.

Verify if MariaDB service is running or not using command:

sudo service mysql status

Sample output:

● mysql.service - LSB: Start and stop the mysql database server daemon
 Loaded: loaded (/etc/init.d/mysql; bad; vendor preset: enabled)
 Active: active (running) since Fri 2016-06-03 19:31:46 IST; 1min 34s ago
 Docs: man:systemd-sysv-generator(8)
 CGroup: /system.slice/mysql.service
 ├─2558 /bin/bash /usr/bin/mysqld_safe
 ├─2559 logger -p daemon err -t /etc/init.d/mysql -i
 ├─2703 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-log-error --pid-file=
 └─2704 logger -t mysqld -p daemon error

Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.column_stats OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.columns_priv OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.db OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.event OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.func OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.gtid_slave_pos OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.help_category OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.help_keyword OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2755]: mysql.help_relation OK
Jun 03 19:31:48 server /etc/mysql/debian-start[2828]: Triggering myisam-recover for all MyISAM tables and aria-recover for all Aria tables
lines 1-20/20 (END)

3. Install PHP

To install PHP, run:

sudo apt-get install php-fpm php-mysql

After installing PHP, we need to secure it by doing a simple change.

To do so, edit php.ini file:

sudo nano /etc/php/7.0/fpm/php.ini

Find the following line:

;cgi.fix_pathinfo=1

Uncomment it and change its value from 1 to 0 (zero).

cgi.fix_pathinfo=0

Save and close the file. Then, restart PHP-FPM service to take effect the changes.

sudo systemctl restart php7.0-fpm

Check PHP-FPM service is running or not using command:

sudo systemctl status php7.0-fpm

Sample output:

● php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager
 Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled)
 Active: active (running) since Fri 2016-06-03 19:40:22 IST; 11s ago
 Process: 10103 ExecStartPre=/usr/lib/php/php7.0-fpm-checkconf (code=exited, status=0/SUCCESS)
 Main PID: 10112 (php-fpm7.0)
 Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
 Tasks: 3 (limit: 512)
 CGroup: /system.slice/php7.0-fpm.service
 ├─10112 php-fpm: master process (/etc/php/7.0/fpm/php-fpm.conf) 
 ├─10114 php-fpm: pool www 
 └─10115 php-fpm: pool www

Jun 03 19:40:22 server systemd[1]: Starting The PHP 7.0 FastCGI Process Manager...
Jun 03 19:40:22 server systemd[1]: Started The PHP 7.0 FastCGI Process Manager.

Configure Nginx to use PHP

We need to configure Nginx to use PHP-FPM.

To do so, edit Nginx’s default vhost (Server block) /etc/nginx/sites-available/default file:

sudo nano /etc/nginx/sites-available/default

Find the Server section, and set your Ubuntu server’s FQDN or IP address as shown below. And also, double check if you have added the index.php line.

[...]
server {
 listen 80 default_server;
 listen [::]:80 default_server;

[...]

root /var/www/html;

 # Add index.php to the list if you are using PHP
 index index.php index.html index.htm index.nginx-debian.html;

 server_name server.ostechnix.lan;
[...]

Let us break down the above lines, and see what each line means.

  • listen 80; –> listen for ipv4
  • listen [::]:80 default_server ; –> listen for ipv6
  • root /var/www/html; –> Nginx document root directory.
  • server_name server.ostechnix.lan; –> Our Ubuntu server’s FQDN.

Then, scroll down little bit and find the section #location ~ \.php$.

Uncomment and modify the following lines as shown below.

location ~ \.php$ {
 include snippets/fastcgi-php.conf;
 #
 # # With php7.0-cgi alone:
 # fastcgi_pass 127.0.0.1:9000;
 # # With php7.0-fpm:
 fastcgi_pass unix:/run/php/php7.0-fpm.sock;

}

# deny access to .htaccess files, if Apache's document root
 # concurs with nginx's one
 #
 location ~ /\.ht {
 deny all;
 }

Save and exit the file.

Check the Nginx configuration file for any syntax errors using command:

sudo nginx -t

Sample output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If you don’t see any errors, restart nginx service to take effect the changes.

To do so, run:

sudo systemctl restart nginx

Or

sudo service nginx restart

Now, let us create a sample PHP file to test the PHP configuration via browser.

To do so, create a file called info.php under Nginx document root folder.

sudo nano /var/www/html/info.php

Add the following lines:

<?php
phpinfo();
?>

Save and quit the file. Restart nginx service to take effect the changes.

Then, open your web browser and navigate to http://IP-address/info.php.

You will see the PHP details.

Congratulations! PHP is working!!

Install PHP modules

To improve the functionality of PHP, you can install some additional PHP modules.

To list the available PHP modules, run:

sudo apt-cache search php- | less

Sample output:

Use and arrows to move up and down between the result. To exit from the result, type q.

To find the details of any particular php module, for example php-gd, run:

sudo apt-cache show php-gd

To install a php module run:

sudo apt-get install php-gd

To install all modules (not necessary though), run:

sudo apt-get install php*

Do not forget to restart Nginx service after installing any php module.

Congratulations! We have successfully setup LEMP stack in Ubuntu 16.04 LTS server.

Start deploying websites and web applications in your new LEMP web stack.

Cheers!