on Install LEMP (Nginx, MariaDB and PHP-FPM ) stack on Ubuntu 14.04

Setting up a web server is not a difficult task to perform if you have a basic understanding of Linux administration. Since you are reading this article, I assume you know what LEMP stands for, so I will not go into the explanation of the acronym.

Before anything, run apt-get update to get the new list of available packages.

sudo apt-get update

Nginx

At the time of writing the latest Nginx package available in Ubuntu's repositories is version 1.4.6. To install it, run:

sudo apt-get install nginx

If you want to install the latest stable Nginx version (at the time of writing, version 1.6.2) from PPA, run the following commands:

sudo apt-get install python-software-properties
sudo add-apt-repository ppa:nginx/stable
sudo apt-get update
sudo apt-get install nginx

Nginx service will start automatically after the installation is complete and it will be set to start automatically on boot. To confirm that the Nginx has been successfully installed, point your web browser to your server's IP address and you should see "Welcome to nginx".

Now, let's make some changes to the configuration. The main Nginx configuration file is /etc/nginx/nginx.conf.

It is always a good practice to make a backup of any file before you make changes:
cp /etc/nginx/nginx.conf{,.backup}

Open the configuration file with your editor of choice and replace the content with the following:

sudo vim /etc/nginx/nginx.conf
user www-data www-data;
worker_processes 1;
worker_rlimit_nofile 2096;

pid /run/nginx.pid;

events {
  worker_connections 2048;
}

http {
  server_tokens off;
  include       mime.types;
  default_type  application/octet-stream;

  charset_types text/xml text/plain text/vnd.wap.wml application/x-javascript application/rss+xml text/css application/javascript application/json;

  access_log /var/log/nginx/access.log;
  error_log /var/log/nginx/error.log;

  keepalive_timeout 20;
  sendfile        on;
  tcp_nopush      on;

  gzip on;
  gzip_comp_level    5;
  gzip_min_length    256;
  gzip_proxied       any;
  gzip_vary          on;

  gzip_types
    application/atom+xml
    application/javascript
    application/json
    application/rss+xml
    application/vnd.ms-fontobject
    application/x-font-ttf
    application/x-web-app-manifest+json
    application/xhtml+xml
    application/xml
    font/opentype
    image/svg+xml
    image/x-icon
    text/css
    text/plain
    text/x-component;
  
  include /etc/nginx/conf.d/*.conf;
  include /etc/nginx/sites-enabled/*;
}

Set the worker_processes to the number of CPU cores your machine has. To find the number of CPU cores run :

grep --count processor /proc/cpuinfo

For example if you have one CPU core. Set it to "1".

Test the configuration for syntax errors and restart the service:

sudo nginx -t
sudo service nginx restart

The settings above are sufficient for most situations, but you can review and change the settings to meet your needs.

MariaDB

Ubuntu 14.04 comes with MariaDB 5.5 (the drop-in replacement for MySQL), but we will install the latest stable version of MariaDB version 10.0. To install MariaDB on your Ubuntu system run the following commands:

sudo apt-get install software-properties-common
sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
sudo add-apt-repository 'deb http://ftp.utexas.edu/mariadb/repo/10.0/ubuntu trusty main'
sudo apt-get update
sudo apt-get install mariadb-server

During the installation you will be asked to set the root password. The MariaDB service will also be set to start automatically on boot.

For testing, you can try to connect to MariaDB as the root user:

mysql -u root -p

You will see an output like the following:

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 57
Server version: 10.0.14-MariaDB-1~trusty-log mariadb.org binary distribution

Copyright (c) 2000, 2014, Oracle, SkySQL Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 

To secure the default installation of MariaDB, run the following command:

sudo mysql_secure_installation

When promted, enter your MariaDB root password, remove anonymous users, disable remote root logins, remove the test database and reload privilege tables. Basically you should answer "Y" to all questions.

The main configuration file for MariaDB on an Ubuntu 14.04 system is /etc/mysql/my.cnf. The optimal configuration depends on your hardware and intended use. We can use a tool called MySQLTuner to tweak our MariaDB configuration.

To install MySQLTuner run the following command:

sudo apt-get install mysqltuner

Run MySQLTuner with the following command and enter root and your MariaDB root password when promted:

sudo mysqltuner

For more accurate recommendations, you should run mysqltuner after MariaDB instance run for at least 24 hours.

Carefully read the output, especially the recommendations at the end. It will show you which variables you should adjust in the [mysqld] section of the /etc/mysql/my.cnf file.

Do not forget to restart the MariaDB service if you make changes in the configuration file:

sudo service mysql restart

PHP-FPM

At the time of writing the latest PHP FPM package available in Ubuntu's repositories is version 5.5. To install it, run:

sudo apt-get install php5-fpm 

Again, PHP FPM service will start automatically after the installation is complete and it will be set to start automatically on boot. We will also install and enable some PHP modules such as:

  • PHP CLI - For running PHP from the command line
  • PHP MySQLnd - Allows PHP to communicate with MySQL/MariaDB databases.
  • PHP Mcrypt - Mcrypt library, which supports a wide variety of block algorithms
  • PHP GD - The GD graphics library
sudo apt-get install php5-cli php5-mysqlnd php5-mcrypt php5-gd
sudo php5enmod mcrypt

To view the installed PHP version type php -v. The output should be as follows:

➜  ~  php -v
PHP 5.5.9-1ubuntu4.4 (cli) (built: Sep  4 2014 06:56:34) 
Copyright (c) 1997-2014 The PHP Group
Zend Engine v2.5.0, Copyright (c) 1998-2014 Zend Technologies
    with Zend OPcache v7.0.3, Copyright (c) 1999-2014, by Zend Technologies

As you can see from output above the PHP 5.5 comes with OpCache out of the box.

The main PHP-FPM configuration file is /etc/php5/fpm/php-fpm.conf, and in general the default values are good enough. The PHP initialization file php.ini is located in the /etc/php5/fpm/ directory, We will make some changes to the default configuration:

sudo cp /etc/php5/fpm/php.ini{,.backup}
sudo sed -i "s/^;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/" /etc/php5/fpm/php.ini
sudo sed -i "s/^upload_max_filesize = .*/upload_max_filesize = 64M/" /etc/php5/fpm/php.ini
sudo sed -i "s/^;date.timezone.*/date.timezone = Europe\/Skopje/" /etc/php5/fpm/php.ini
sudo service php5-fpm restart

The above commands will make a backup of the php.ini file, change cgi.fix_pathinfo from 1 to 0, increase the maximum allowed size for uploaded files from 2MB to 64MB, set the PHP date.timezone to the appropriate time zone, in my case Europe/Skopje and restart the PHP-FPM service. Of course, feel free to edit the ini file to suit your needs.

The pool configuration files are located in the /etc/php5/fpm/pool.d/ directory. Every file in this directory ending with .conf is automatically included in the PHP-FPM configuration. The best approach is to use one pool per site which will improve maintainability and security.

In the default PHP-FPM pool www.conf file the process manager (manager who control the number of child processes) is set on dynamic. I personally prefer to use the ondemand mode which will only spawn new processes when they are needed.

First make a backup of the original /etc/php5/fpm/pool.d/www.conf file:

sudo cp /etc/php5/fpm/pool.d/www.conf{,.backup}

and edit the file as follows:

[www]
user = www-data
group = www-data
listen = /var/run/php5-fpm.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 5
pm.process_idle_timeout = 10s;
pm.max_requests = 200
chdir = /

Lastly, restart the PHP-FPM service with:

sudo service php5-fpm restart

Testing

To test if PHP FPM is working as expected we need to make few changes.

First edit the /etc/nginx/sites-available/default file and add a php location block as follows:

# content of the /etc/nginx/sites-available/default file
server {
  listen 80 default_server;
  server_name localhost;

  root /var/www/html;
  index index.html index.htm index.php;

  charset utf-8;

  location / {
    try_files $uri $uri/ =404;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    include fastcgi_params;
    fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
    fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;
  }
}

Restart the Nginx service for changes to take effect with:

sudo nginx -t
sudo service nginx restart

In the root directory of your default nginx server, we will create a file named phpinfo.php.

// content of the /var/www/html/phpinfo.php file
<?php 
phpinfo();

Finally, if everything is setup properly, you should see the php configuration of your server by visiting http://Server_IP/phpinfo.php

By now you should have a fully working LEMP stack, on which you can install WordPress, Drupal, Laravel or any other PHP based aplications.