Skip to content

Instantly share code, notes, and snippets.

@exanup
Last active February 19, 2018 13:10
Show Gist options
  • Save exanup/d92a47294d46bf4c671000ed4809af80 to your computer and use it in GitHub Desktop.
Save exanup/d92a47294d46bf4c671000ed4809af80 to your computer and use it in GitHub Desktop.
A Relatively Secure LEMP Server Stack Setup in Ubuntu 17.10 + phpMyAdmin

A Relatively Secure LEMP Server Stack Setup in Ubuntu 17.10 + phpMyAdmin

By Anup Dhakal

Introduction

In this guide, LEMP stands for Linux, Nginx (pronounced as Engine-X) , MariaDB (a drop in replacement for MySQL) and PHP (PHP Hypertext Preprocessor). Also, as a bonus, we will learn to setup phpMyAdmin too.

I have gone through many websites in order to learn even just the basics of setting up a LEMP server. Hence I know the hassle. Here I have created a through guide to help someone relatively new to setup a powerful LEMP machine easily and effortlessly. I hope this guide comes to someone's rescue.

The instructions on this guide has been tested to work on a fresh install of Ubuntu 17.10 as the time of this writing (NPT 02/09/2018 2.42PM). Also, the system was fully updated before we started with the LEMP setup procedure.

And for any other platform, this guide should still serve a useful resource. The "mini goals" are well defined in various paragraphs. And one can easily look elsewhere for specific instructions for that platform to achieve same "mini goal" one at a time.

For a system already running other version of server stacks (example LAMP), some additional steps (like removing those packages or disabling them) might be required. That is beyond the scope of this guide.

Specifications/Target:

  • Ubuntu v17.10
  • Nginx v1.12
  • PHP v7.2
  • MariaDB v10.2
  • (Bonus) phpMyAdmin v4.6

But before we start, let's quickly make sure that we have some basic tools ready. Run the following commands in the terminal.

sudo apt update
sudo apt install wget
sudo apt install software-properties-common

Now let's start!

Custom Repositories

Before beginning the installation, we want to add some repositories which will give us the latest corresponding packages for our server stack.

Nginx Repository

We will go with the default version of Nginx provided by Ubuntu because, as the time of this writing, prebuilt package for Ubuntu "artful" release was not available from Nginx. And the Ubuntu version available was the stable version just two subversions late, which is good enough!

MariaDB Repository

We will add the MariaDB stable repository. Run the following commands in the terminal to do so. We need to accept any prompts, if asked.

sudo apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xF1656F24C74CD1D8
sudo add-apt-repository 'deb [arch=amd64,i386] http://sgp1.mirrors.digitalocean.com/mariadb/repo/10.2/ubuntu artful main'

Please note that the mirror here I have used is from Digital Ocean (Singapore), because it is one of the nearest mirrors providing latest version of Nginx from my location. To select any other mirror, and get corresponding setup instructions, we can visit the MariaDB Repository webpage here. We have to make sure that we choose Distro Ubuntu, Release 17.10 "artful", Version 10.2 [Stable] and finally the mirror nearest to us.

PHP Repository

The repository here we are going to install is the PHP PPA by Ondrej. We can update our system with "unsupported" packages from this "untrusted" PPA by adding ppa:ondrej/php to our system's Software Sources. The following commands will help us to do so. We need to accept any prompts, if asked.

sudo add-apt-repository ppa:ondrej/php

We might feel a little bit confused by the terms "untrusted PPA", but there is actually no reason to worry. We just need to remember that, unlike Nginx's or the MariaDB's repositories, this is not an official upgrade path. But the PPA is well known, and is relatively safe to use.

(Bonus) phpMyAdmin Repository

As with nginx, we will just use the default Ubuntu provided pre-built binary package for phpMyAdmin. Hence, we are not adding any new repositories here.

Actual Installation

Let's finally begin the actual installations processes.

Update APT

First, we want to make sure we have the latest records in our local packages registry. Let's run the following command in the terminal like so.

sudo apt update

Installing Nginx

First thing we’re going to install is the server called Nginx.

sudo apt install nginx

We can check if Nginx is installed by typing nginx -v in the terminal.

Installing MariaDB

Now we want to install the database management system (DBMS). We choose MariaDB, which is a modern relational DBMS. It is the drop in replacement for MySQL.

sudo apt install mariadb-server mariadb-client

We can check if MariaDB is installed by executing mysql --version in the terminal.

Even though we are setting up MariaDB, it's actually a derivation of MySQL and hence many packages we install here may have term "mysql" in them. For an example, PHP makes use of the package php-mysql as the database driver for MySQL as well as MariaDB.

Installing PHP

Next thing we want to install is PHP. We need to install PHP with a few extensions that are mandatory for modern web applications.

sudo apt install php-cli php-fpm php-zip php-xml php-mbstring php-mcrypt php-curl php-gd php-mysql php-sqlite3 php-bz2 php-gettext php-pear php-phpseclib php-tcpdf

We may run php -v in the terminal to check the version of PHP installed.

Configurations

Time to make the installations "talk" to each other.

Configuring Nginx

We don't need to change anything right now. But if we want to, we can change the main configuration of Nginx as follows:

sudo nano /etc/nginx/nginx.conf

In the config file, notice the line with user www-data. This means Nginx will run as the user www-data. We should not forget to run the following if we made changes to any configuration file of Nginx.

sudo systemctl restart nginx.service

Configuring PHP to work with Nginx

In order for PHP and Nginx to work together, we need to configure both of them. We need to make sure that PHP-FPM (FastCGI Process Manager) runs as the same user as Nginx. And for that we need to run the following command in the terminal

sudo nano /etc/php/7.2/fpm/pool.d/www.conf

And change the relevant lines as:

...
user = www-data
group = www-data
...
listen.owner = www-data
listen.group = www-data
...

Note the command where we used ... php/7.2/fpm ... . We want to make sure that 7.2 is the version that we actually have installed in our system. Refer this section to go back and see how we installed PHP and PHP-FPM, and how to see the version of PHP installed.

If we made changes to the configuration, we need to run the following in the terminal to load the changes.

sudo systemctl restart php7.2-fpm.service

Default Site

Now comes the fun part where we create a default site that supports PHP. In our case, we want ~/www as our directory of all websites. Normally, /var/www is used as the default one. Here we want to change it to a custom directory inside our home directory, as mentioned above.

Please note extra carefully that this might be nor the smartest neither the safest idea to let the web directory to have same ownership as the "human" user! But we are doing this for our ease. Please do remember that "ease" and "security" usually always contradict with each other!

First, we want to make sure the directory exists. Let's create a default site directory _default_ with the following command.

mkdir -p ~/www/_default_/public

Note that to add other sites, we can follow a similar pattern. We may create a new folder for each site, which has a public folder in it as the public entry point of the site.

Now to edit the default site configuration, let's run the following command in the terminal

sudo nano /etc/nginx/conf.d/default.conf

and replace its content with this:

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

    root /home/[OUR_USERNAME]/www/_default_/public;

    index index.html index.htm index.php;

    server_name _;

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

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

}

Please note that we need to change [OUR_USERNAME] from above config file to our actual username.

There is one important thing that we might miss here. Remember previously in the Nginx Repository section, where we did not change the repository to the Nginx default, and instead reverted back to use the default provided by Ubuntu?

Problem with Ubuntu provided version is that the Nginx configuration concept is somewhat like Apache's httpd. The behaviour is to load all the configurations from /etc/nginx/sites-enabled. And this very direcotry has default site configured from /etc/nginx/sites-enabled/default, which is infact just a symbolic link to /etc/nginx/sites-available/default. This should sound familier to someone who has worked with Apache httpd configurations in Ubuntu.

But we have configured our default site in /etc/nginx/conf.d/default.conf. So, to prevent the conflict, we need to disable the default included site. Removing the above-mentioned symbolic link should do the trick for us. Run the followind commands:

sudo rm /etc/nginx/sites-enabled/default

Now let's run the following to reload our new configuration.

sudo systemctl restart nginx.service

Now we should be able to see on browser that http://localhost actually works, and most probably shows an empty index.

**Ba Dum Tis**

We can put any file in the ~/www/_default_/public directory and it should be showing in the browser after a refresh.

Configuring MariaDB

This one is easy. Let's open our terminal and run the following:

sudo mysql_secure_installation

We just need to carefully follow all of the prompts and we will properly set up MariaDB.

(Bonus) Installing phpMyAdmin

Setting Up Host

We want to be able to lunch phpMyAdmin by going to http://phpmyadmin.app in the address bar of the browser.

So, first of all, run:

sudo nano /etc/hosts

and add an entry as follows:

...
127.1.1.1    phpmyadmin.app
...

phpMyAdmin

Run the following commands to install phpmyadmin:

sudo apt install phpmyadmin

NOTE: We will just press [tab] when asked which web server we have. This is because phpMyAdmin does not provide us with an option for Nginx. We will continue all other setup as usual. Also, when prompted for a password by phpmyadmin, we can insert any random password we want.

Setting Up Server Block

Now, we will setup an Nginx server block (a.k.a. virtual host in Apache httpd).

Let's run the following command to create a site (configuration file).

sudo touch /etc/nginx/conf.d/phpmyadmin.conf

Let's open it with:

sudo nano /etc/nginx/conf.d/phpmyadmin.conf

and add the contents as follows.

server {
    listen 80;

    root /usr/share/phpmyadmin; # make sure to enter the correct location of phpmyadmin here
    index index.php index.html index.htm;

    server_name phpmyadmin.app;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri /index.php =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

Activating the server block

Now we have to restart Nginx to activate our new site (config file) by running:

sudo systemctl restart nginx.service

Try hitting http://phpmyadmin.app and it should work!

Conclusion

There we have it! We should by now have a working and relatively secure LEMP server stack with Nginx running at http://localhost, as well as our phpMyAdmin app running at http://phpmyadmin.app

In this guide we didn't talk anything about firewall. This is because a fresh install of "vanilla" Ubuntu 17.10 should not have one running it automatically. We may research about it later if we wish to. Right now, that would be beyond the scope of this guide.

So, did you find this guide helpful? Feedbacks are precious. Suggestions are highly appreciated.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment