Apr.19

Install and Configure LEMP Stack (Linux, Nginx, MySQL & PHP) on Ubuntu 14.04

LEMP Stack

LEMP Stack is an archetypal model of web service solution stacks, named as an acronym of the names of its original four components: the Linux operating system, the Nginx(engine-x) HTTP Server, the MySQL relational database management system (RDBMS), and the PHP programming language. As a solution stack, LEMP is suitable for building dynamic web sites and web applications to increase the ability of the server to scale in response to demand.

In this tutorial I will also include, on how to install and securely configure phpMyAdmin instance—that handle the administration of MySQL over the Web.

Getting Started

I will be installing the required packages on Ubuntu 14.04 LTS (Trusty Tahr). In addition, I’ve had great success on using Digital Ocean‘s and Linode‘s Virtual Private Server, they are easy to use and can typically be setup in 55 seconds. I will assume you have your server all setup, and you are ready to begin at the command line, so lets get started.

Nginx
  • Install Nginx
  • Nginx (pronounced as engine-x) is a free, open-source, high-performance HTTP server and reverse proxy, as well as an IMAP/POP3 proxy server written by Igor Sysoev.

    First lets make sure our server is all up-to-date. Enter the following command in your terminal:

    sudo apt-get update

    Now, install Nginx using this command:

    sudo apt-get install nginx

    Start Nginx service using the command:

    sudo service nginx start
  • Test Nginx
  • Open up your web browser and navigate to http://ip-address/ or http://localhost/. You will see a screen something like below.

  • Configure Nginx
  • Check the No. of CPU(s) in your server using this command:

    lscpu

    Now Open the file /etc/nginx/nginx.conf in any editor:

    sudo nano /etc/nginx/nginx.conf

    Adjust the worker_processes (i.e No. of CPU’s in your server). In my case it’s 1. So I set the worker_processes to 1.

    worker_processes 1;

    Restart Nginx service:

    sudo service nginx restart

    The default vhost is defined in the file /etc/nginx/sites-available/default . And the virtual hosts are defined in server {} containers – let’s modify it as follows:

    Open the file /etc/nginx/sites-available/default in any editor.

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

    Under the server section, set the server_name to FQDN (Fully Qualified Domain Name) or IP address as shown below. Make sure you’ve also added index.php, See the example below:

    […]

    server {

    listen 80 default_server;

    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;

    index index.php index.html index.htm;

    # Make site accessible from http://localhost/

    server_name 127.0.0.1 ;

    […]

    Explanation:

       listen 80; -> listen for ipv4

       listen [::]:80 default_server ipv6only=on; -> listen for ipv6

       root /var/www/html; –> document root directory.

       server_name 127.0.0.1; –> Server FQDN

    Now, scroll down further and find the section #location ~ \.php$. Uncomment and modify the following lines as shown below.

    […]

    location ~ \.php$ {

    try_files $uri =404; -> Add this line

    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    #    # NOTE: You should have “cgi.fix_pathinfo = 0;” in php.ini

    #

    #    # With php5-cgi alone:

    #    fastcgi_pass 127.0.0.1:9000;

    #    # With php5-fpm:

    fastcgi_pass unix:/var/run/php5-fpm.sock;

    fastcgi_index index.php;

    include fastcgi_params;

    }

    […]

    Explanation:

    Here, I added an extra line ‘ try_files $uri =404; ‘ to prevent zero day exploits.

    Save and close the file.

  • Test Nginx Configuration
  • Test the nginx configuration 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

    Restart Nginx service:

    sudo service nginx restart
MySQL
  • Install MySQL
  • MySQL is a relational database management system (RDBMS) that runs as a server providing multi-user access to a number of databases.

    sudo apt-get install mysql-server-5.6 mysql-client-5.6

    During installation, you’ll be asked to setup the MySQL “root” user password. Enter the password and select Ok.

    Re-enter the password.

    MySQL is now installed.

  • Verify MySQL status
  • You can verify the MySQL server status using command:

    sudo service mysql status

    Sample output:

    mysql start/running, process 980

  • Configure MySQL
  • We need to tell MySQL to generate the directory structure it needs to store its databases and information. We can do this by using this command:

    sudo mysql_install_db

    Next, you’ll have to run a simple security script that will prompt you to modify some insecure defaults in the terminal. Begin the script by using this command:

    sudo mysql_secure_installation

    You will need to enter the MySQL root password that you selected during installation.

    Next, you will be ask if you want to change that password. If you are happy with your MySQL root password, type “N” for “no” and hit “ENTER”. Afterwards, you will be prompted to remove some test users and databases. You should just hit “ENTER” through these prompts to remove the unsafe default settings.

    Once the script has been run, MySQL is ready to go.

PHP
  • Install PHP
  • PHP (recursive acronym for PHP: Hypertext Preprocessor) is a widely used open-source general purpose scripting language that is especially suited for web development and can be embedded into HTML.

    Install PHP with following command:

    sudo apt-get install php5 php5-fpm

    Install PHP MySQL library with the following command:

    For MySQL version 5.5 and below.

    sudo apt-get install php5-mysql

    For MySQL version 5.6.

    sudo apt-get install php5-mysqlnd

  • Configure PHP
  • Open php.ini file in any editor:

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

    Find the line “ cgi.fix_pathinfo=1 “, uncomment it and change the value 1 to 0 .

    […]

    cgi.fix_pathinfo=0

    […]

    Now restart PHP-FPM service.

    sudo service php5-fpm restart

    To check whether php5-fpm is running or not. Use the command below:

    sudo service php5-fpm status

    Sample output:

    php5-fpm start/running, process 1124

  • Test PHP
  • Now create the following PHP file in the nginx document root folder /usr/share/nginx/html :

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

    Add the following lines in the file.

    <?php

    phpinfo();

    ?>

    Save and close the file.

    Navigate to http://server-ip-address/info.php . It will display all the details about PHP such as version, modules, build date and commands, etc.

    If this was successful, then your PHP is working as expected.

  • PHP-FPM Use A TCP Connection
  • By default PHP-FPM listens on the socket /var/run/php5-fpm.sock . If you want to make PHP-FPM use a TCP connection, open the file /etc/php5/fpm/pool.d/www.conf .

    sudo nano /etc/php5/fpm/pool.d/www.conf

    Modify the listen line to look as follows:

    […]

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

    listen = 127.0.0.1:9000

    […]

    Explanation:

    This will make PHP-FPM listen on port 9000 on the IP 127.0.0.1 (localhost) . Make sure you use a port that is not in use on your system.

    Save and close the file. Restart php5-fpm service.

    sudo service php5-fpm restart

    Now open and modify the nginx configuration file:

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

    Find the line fastcgi_pass unix:/var/run/php5-fpm.sock; and change it to fastcgi_pass 127.0.0.1:9000; as shown below:

    […]

    location ~ \.php$ {

    try_files $uri =404;

    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    #    # NOTE: You should have “cgi.fix_pathinfo = 0;” in php.ini

    #

    #    # With php5-cgi alone:

    fastcgi_pass 127.0.0.1:9000;

    #    # With php5-fpm:

    #    fastcgi_pass unix:/var/run/php5-fpm.sock;

    fastcgi_index index.php;

    include fastcgi_params;

    }

    […]

    Save and close the file. Finally restart nginx service.

    sudo service nginx restart

phpMyAdmin
  • Install phpMyAdmin
  • phpMyAdmin is a free and open source tool written in PHP intended to handle the administration of MySQL with the use of a web browser. It can perform various tasks such as creating, modifying or deleting databases, tables, fields or rows; executing SQL statements; or managing users and permissions.

    It is available in the Official Debian repositories. So install it with command:

    sudo apt-get install phpmyadmin

    Select the web server that should be automatically configured to run phpMyAdmin.

    By default, nginx will not be displayed here. So, select apache or lighttpd, and we will configure phpmyadmin to work with nginx webserver later.

    When the first prompt appears, apache2 is highlighted, but not selected. If you do not hit “SPACE” to select Apache, the installer will not move the necessary files during installation. Hit “SPACE”, “TAB”, and then “ENTER” to select Apache2.

    Select Yes to configure database for phpmyadmin with dbconfig-common.

    Enter password of the database’s administrative user (i.e MySQL root user password).

    Enter MySQL application password for phpmyadmin.

    Re-enter the password.

    phpMyAdmin has been successfully installed now.

    Create a symbolic link between phpMyAdmin and the website root directory. Here our website root document directory is /usr/share/nginx/html/ .

    sudo ln -s /usr/share/phpmyadmin/ /usr/share/nginx/html/

    Restart nginx server.

    sudo service nginx restart

  • Access phpMyAdmin in Web Console
  • Now you can access the phpMyAdmin console by navigating to http://server-ip-address/phpmyadmin from your browser.

    Enter your MySQL username and password which you have given in previous steps.

    You will be redirected to phpMyAdmin main web interface. This is how my phpMyAdmin dashboard looks.

    Now you can manage your MySQL databases from phpMyAdmin web interface.

  • Fix “The mcrypt extension is missing. Please check your PHP configuration.”
  • Install mcrypt extension for PHP with following command:

    sudo apt-get install php5-mcrypt

    Enable the mcrypt extension with following command:

    sudo php5enmod mcrypt

    Restart Nginx service:

    sudo service nginx restart

    Restart PHP-FPM service:

    sudo service php5-fpm restart

    With that, your phpMyAdmin installation is now operational.

  • Secure your phpMyAdmin Web Console
  • The phpMyAdmin web console installed on our server should be completely usable at this point. However, by installing a web interface, we have exposed our MySQL system to the outside world.

    Even with the included authentication screen, this is quite a problem. Because of phpMyAdmin’s popularity combined with the large amount of data it provides access to, installations like these are common targets for attackers.

    We will implement a simple strategy that I commonly use to lessen the chances of our installation being targeted and compromised. We will create an additional, web server-level authentication gateway that must be passed before even getting to the phpMyAdmin login screen.

  • Setting up a Web Server Authentication Gate
  • From this forward on, we will need to modify our Nginx configuration file again. And we have to create a password file that will store our authentication credentials. Nginx requires that passwords be encrypted so we will be using OpenSSL suite, which should already be installed on your server.

    To create an encrypted password, use the following command:

    openssl passwd

    You will be prompted to enter and confirm the password that you wish to use. The utility will then display an encrypted version of the password that will look something like this:

    j5ZOrrW0.X5pN

    Copy this value, as you will need to paste it into the authentication file we will about to create.

    Now, create an authentication file. We will call this file pma_pass and place it in the Nginx configuration directory:

    sudo nano /etc/nginx/pma_pass

    Within this file, you simply need to specify the username you would like to use, followed by a colon (:), followed by the encrypted version of your password you received from the openssl passwd utility.

    We are going to name our user demo , but you should choose a different username. The content of this file will look like this:

    demo:j5ZOrrW0.X5pN

    Save and close the file when you are finished.

    Now, we are ready to modify our Nginx configuration file. Open this file in your text editor to get started:

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

    Within this file, we need to add a new location section. This will target the location we chose for our phpMyAdmin interface.

    Create this section within the server block, but outside of any other blocks. We will put our new location block below the location / block, see the highlighted block for example:

    […]

    server {

    […]

    location / {

    try_files $uri $uri/ =404;

    }

    location /phpmyadmin {

    auth_basic “Restricted Area! Authorized Penguin Only”;

    auth_basic_user_file /etc/nginx/pma_pass;

    }

    […]

    }

    […]

    Within the highlighted block, as you can see—we need to set the value of a directive called auth_basic to an authentication message that our prompt will display to users. We do not want to indicate to unauthenticated users what we are protecting, so do not give specific details. We will just use “Restricted Area! Authorized Penguin Only” in our example.

    We then need to use a directive called auth_basic_user_file to point our web server to the authentication file that we created. Nginx will prompt the user for authentication details and check that the inputted values match what it finds in the specified file.

    Save and close the file when you are finished.

    To implement our new authentication gate, we must restart the web server:

    sudo service nginx restart

    Now, if we visit our phpMyAdmin location in our web browser (you may have to clear your cache or use a different browser session if you have already been using phpMyAdmin), you should be prompted for the User Name and Password you added to the pma_pass file:

    Once you enter your correct credentials, you will be taken to the default phpMyAdmin login page. This added layer of protection will help keep your MySQL logs clean of authentication attempts in addition to the added security benefit.

That’s it! Congratulation your LEMP Stack server is ready for use.

If I can get my codes to function as I want, I’ve succeeded as a Programmer.
Tutorials
Share this Story:
  • facebook
  • twitter
  • gplus

About JiNexus

DevOp (Development and Operations) with a focus on PHP web applications and cloud-based Ubuntu servers.
Experienced in building large custom MVC web applications in PHP, using frameworks like Zend Framework, Apigility, Doctrine ORM, Code Igniter, Phalcon and WordPress. Currently focusing on back-end web applications in PHP, I also like to venture out into the Bootstrap-based front end world using HTML, CSS and JavaScript (jQuery mainly).
Sometimes one needs to experiment with other technologies and I've done this with Python.

P.S.
"Life is like programming. We fail to compile, because realization comes from warnings and success comes from experience."

Comments(1)

  1. BobbuBrowne
    142 days ago

    Hello! Cool post, amazing!!!

Leave a comment

Comment