How to Install Nginx, MariaDB and PHP (LEMP) on Ubuntu 16.04

LEMP

The LEMP Stack refers to a group of softwares which together can run dynamic websites. It is an acronym for Linux, (E)Nginx, MySQL (or MariaDB) and PHP.

In this tutorial we will learn how to setup a LEMP Stack on Ubuntu 16.04.

Requirements

An Ubuntu Server 16.04 with an sudoer account. Note: The default user –  ubuntu – on AWS EC2 or Lightsail already comes with sudo access so you can follow this tutorial directly by using the ubuntu account. To setup a DigitalOcean, Vultr, Linode or local server, follow  Basic Setup of Ubuntu Server 16.04.

Installing Nginx (web server)

Nginx is a web server which can also be used as a reverse proxy, load balancer and HTTP cache. In this tutorial we will use it as a web server to serve static pages and a reverse proxy to PHP-FPM for dynamic content.

Update the system and install Nginx.

sudo apt update
sudo apt install nginx

This will install and run Nginx. If you have installed and enabled ufw then enable the Nginx profile so that Nginx can be reached on port 80.

sudo ufw allow 'Nginx HTTP'

If your server is on AWS then edit your security group settings and add a rule to allow incoming connections on port 80.

On your browser, navigate to your IP address or domain.

http://your_domain_or_server_ip 

You should see the default Nginx landing page.

Your Nginx installation was successful.

Install MariaDB to Manage Data

MariaDB is a community-developed fork of the MySQL relational database management system intended to remain free under the GNU GPL.

Since MariaDB is under heavy development, it’s advisable to install it from its own repositories instead of Ubuntu repositories. To add MariaDB repositories, choose your distribution (Ubuntu), release (16.04), version (10.2) and nearest mirror from:

https://downloads.mariadb.org/mariadb/repositories/

Once you select your nearest mirror, you will be presented with the code to add repositories. Copy the code from there and add MariaDB repositories. The code is similar to the following.

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,ppc64el] http://ossm.utm.my/mariadb/repo/10.2/ubuntu xenial main'

Once the key is imported and the repository added you can install MariaDB with:

sudo apt update
sudo apt install mariadb-server

Enter a secure password and press “enter” for the root when asked.

MariaDB is installed and running now. Check its status by typing:

sudo systemctl status mysql
� mariadb.service - MariaDB 10.2.12 database server
Loaded: loaded (/lib/systemd/system/mariadb.service; enabled; vendor preset: enabled)
Drop-In: /etc/systemd/system/mariadb.service.d
��migrated-from-my.cnf-settings.conf
Active: active (running) since Fri 2018-02-09 17:01:56 UTC; 1h 15min ago
Docs: man:mysqld(8)
https://mariadb.com/kb/en/library/systemd/
Main PID: 22311 (mysqld)
Status: "Taking your SQL requests now..."
CGroup: /system.slice/mariadb.service
��22311 /usr/sbin/mysqld

If it’s not enabled or not running then enable it and start it by:

sudo systemctl enable mysql
sudo systemctl start mysql

Secure the installation by removing test databases etc. by running:

 sudo mysql_secure_installation

Enter the password which you enter during installation and answer the questions that follow.

  • When asked about changing the password, answer “N” (no) .
  • Remove the anonymous user account by answering “Y”.
  • Disallow remote root login by answering “Y”.
  • Remove the test database by answering “Y”.
  • Reload privilege tables by answering “Y”.

MariaDB is now installed and ready to use. Login to MariaDB to test it.

mysql -u root -p

Enter the root password when prompted. You should be able to login successfully. Now logout by typing “Ctrl-d”.

Install PHP for Server Side Scripting

Unlike Apache, Nginx does not run PHP natively so we install “php-fpm”. Install it by using:

sudo apt install php-fpm php-mysql

Configure PHP

By default, PHP enables a highly dangerous setting. This setting instructs PHP to run the nearest matching script if the exact script is not found. We need to disable this setting. Open the configuration file for PHP.

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

Search for the line containing cgi.fix_pathinfo. Uncomment the line by removing the “;” at the start of the line and change it’s vaue to “0”.

cgi.fix_pathinfo=0

Reload php-fpm for the new configuration to take effect.

sudo systemctl reload php7.0-fpm.service

Configure Nginx to use Handle PHP

Open the configuration for the default site.

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

Look for the line starting with index inside the server block and add index.php to the list.

index index.php index.html index.htm index.nginx-debian.html;

Uncomment the location block for PHP and .hhtacces to look like this.

# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000

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;
}

Check for configuration errors by:

sudo nginx -t

Correct any errors if reported else load the new configurations by:

sudo systemctl reload nginx.service

Test the Configuration

Create a small file to test whether the site is running properly.

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

Pate the following content into the file:

<?php
phpinfo();

Save the file and navigate to the file on a browser.

http://your_domain_or_server_ip/info.php

You should see a page similar to the following.

If you see a page similar to the above then you have successfully setup your server.

After testing,  remove the file so that unauthorized people do not get any hint on the server configuration.

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

How to Use Screen on Ubuntu 16.04

GNU Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells.

A remote connection can be interrupted due to many reasons including network outrage. In such a scenario, there is a high probability of losing SSH access in the middle of a task. This may terminate the session and the ongoing job while the system in an unpredictable state. The GNU screen can come to rescue in such a situation.

Installation

It comes pre-installed on Ubuntu Server 16.04. If for any reason, it has been removed, you can install it by the following command.

[code language=”bash”]
sudo apt update
sudo apt install screen
[/code]

Usage

To use screen just type “screen” in a shell/terminal and hit “enter”.

[code language=”bash”] screen [/code]

It will display a long message. Just hit “enter”. You are in a screen terminal now. To verify type “Ctrl+a” followed by “v”. You should see an output similar like “screen 4.03.01 (GNU) 28-Jun-15″.

[code language=”bash”] Ctrl-a v [/code]

[code language=”bash”] screen 4.03.01 (GNU) 28-Jun-15 [/code]

Open a new window within the screen by typing “Ctrl+a” followed by “c”.

[code language=”bash”] Ctrl-a c [/code]

You have opened a new window within the screen. Now run “top” in this window.

[code language=”bash”] top [/code]

To go back to the previous window press “Ctrl+a” followed by “p”.

[code language=”bash”] Ctrl-a p [/code]

Similarly to go to the next window press “n” instead of “p”.

[code language=”bash”] Ctrl-a n [/code]

You can open a few more windows by pressing “Ctrl+a” followed by “c”.

[code language=”bash”]
Ctrl-a c
Ctrl-a c
[/code]

To keep track of all the windows type:

[code language=”bash”] Ctrl-a w [/code]

This will output a numbered list of windows starting from 0 with the current window marked by a star. You can switch to a particular window by pressing “Ctrl+a” followed by the screen number. To switch to the first window type:

[code language=”bash”] Ctrl-a 0 [/code]

Close the shell. Now open a new shell and connect to your server and type “screen -r”.

[code language=”bash”] screen -r [/code]

You should be taken back to where you left off.

If, instead, you see a message similar to the following then the screen has not detached.

[code language=”bash”]
There is a screen on:
1710.pts-0.ip-172-31-28-182 (02/04/18 16:59:55) (Attached)
There is no screen to be resumed.
[/code]

You can reattach the screen by the following command.

[code language=”bash”] screen -x [/code]

To detach a screen any time and get back to the terminal which started the screen, type the following.

[code language=”bash”] Ctrl-a d [/code]

[code language=”bash”] [detached from 1604.pts-0.ip-172-31-28-182] [/code]

The current screen will be detached and sent to the background. Now attach/resume the screen by typing “screen -r”.

[code language=”bash”] screen -r [/code]

 

Basic Setup of Ubuntu Server 16.04

This article covers a few basic configurations recommended for a newly installed public facing Ubuntu Server. You are advised to undertake these steps as soon as possible. In order to execute the steps, first login to your system as root. If your server is at a remote location, use SSH to access your server. Just open a terminal on your PC and login through the following command (replace your_server_ip with your real IPv4 Address).

[code language=”bash”] ssh [email protected]_server_ip [/code]

The root user on a Linux system has very extensive privileges. Given so, it is advisable not to use the root user account on a regular basis as an inadvertent error in a command can lead to catastrophic results. A rather simplified approach is to use the system as a normal user and escalate privileges on a need basis.

Using GNU Screen for Terminal Multiplexing

Note: You may skip this section if you desire.

A remote connection can be interrupted due to many reasons including network outrage. In such a scenario, there is high probability of losing SSH access in the middle of a job. This may terminate the session and the ongoing job while the system in an unpredictable state. The GNU screen can come to rescue in such a situation. In brief, GNU Screen is a full-screen window manager that multiplexes a physical terminal between several processes, typically interactive shells. It comes pre-installed on Ubuntu Server 16.04. To use screen just type “screen” in a shell/terminal and hit “enter”.

[code language=”bash”] screen [/code]

It will display a long message. Just hit “enter”. You are in a screen terminal now. To verify type “Ctrl+a” followed by “v”. You should see an output similar like “screen 4.03.01 (GNU) 28-Jun-15″.

[code language=”bash”] Ctrl-a v [/code]

[code language=”bash”] screen 4.03.01 (GNU) 28-Jun-15 [/code]

Open a new window within the screen by typing “Ctrl+a” followed by “c”.

[code language=”bash”] Ctrl-a c [/code]

You have opened a new window within the screen. Now run “top” in this window.

[code language=”bash”] top [/code]

To go back to the previous window press “Ctrl+a” followed by “p”.

[code language=”bash”] Ctrl-a p [/code]

Similarly to go to the next window press “n” instead of “p”.

[code language=”bash”] Ctrl-a n [/code]

Close the shell. Now open a new shell and connect to your server and type “screen -r”.

[code language=”bash”] screen -r [/code]

You should be taken back to where you left off. If, instead, you see a message similar to the following then the screen has not detached.

[code language=”bash”]
There is a screen on:
1710.pts-0.ip-172-31-28-182 (02/04/18 16:59:55) (Attached)
There is no screen to be resumed.
[/code]

You can reattach the screen by the following command.

[code language=”bash”] screen -x [/code]

You can also detach a screen manually by the following command.

[code language=”bash”] Ctrl-a d [/code]

[code language=”bash”] [detached from 1604.pts-0.ip-172-31-28-182] [/code]

The current screen will be detached and sent to the background. Now attach/resume the screen by typing “screen -r”.

[code language=”bash”] screen -r [/code]

You can refer to the manual of screen for more command details.

[code language=”bash”] man screen [/code]

Creating a New User

While you are logged in as root (if the prompt on the shell is “#” then you are logged in as root else if the prompt is “$” then you are logged in as a non-root user), type the following command (replace saumyakswain with your desired name).

[code language=”bash”]
adduser saumyakswain
[/code]

Provide a strong password and repeat the same when asked. Additionally, you may choose to answer the other questions or you may leave them blank and just press the return (or enter) key.

Root Privileges for the New User

Instead of changing between the root and normal user for administrative and normal tasks, we can give the new user superuser privileges. This way the normal user can perform administrative tasks by adding the command “sudo” the beginning of any command. We can give superuser privileges to a normal user by adding it to the “sudo” group. You can add a user to the sudo group by the following command.

[code language=”bash”]
usermod -aG sudo saumyakswain
[/code]

Public Key Authentication

Logging in remotely using passwords is not a safe practice considering the fact that thousands of bots will be trying to brute force into your system. A more secure option is to use Public Key instead of passwords.

If you have not used public key earlier, you need to generate a key pair on your local system (PC) which can be used to authenticate remote servers. If you already have a public key, skip ahead the key generation step. To generate a ssh key pair, open a new terminal (shell) and enter the following command.

[code language=”bash”]
ssh-keygen
[/code]

Accept the default location of the key file. Next you will be asked for a pass-phrase to secure the key you may leave the pass-phrase blank and hit return.

The command will generate a key-pair – id_rsa the private key and id_rsa.pub – in the .ssh directory of the current user (local). DO NOT share the private key with any one.

In order to use the keys, we need to copy the public component of the key-pair to the sever(s) which we want to login through public key. The easy way to accomplish this is to use the “ssh-copy-id” command. But please be informed that the ssh-copy-id command relies on password authentication for copying the key and hence it will not work if password authentication is disabled. You may temporarily allow password authentication and use ssh-copy-id or use the alternative method of copying the key manually.

Using ssh-copy-id to Copy the Public Key

Type the following command on a terminal replacing the user name and IP address with appropriate values.

[code language=”bash”]
ssh-copy-id [email protected]_server_ip
[/code]

You will be prompted for the password of the user. Provide the password you entered while creating the new user and not the root password. Note: You can omit the username and simply type “ssh-copy-id your_server_ip” if the username on the local system and the remote server are the same.

Manually Copying the Public Key

If you don’t want to enable password authentication then you can copy it manually. To display your public key, type the following command on your local system.

[code language=”bash”]
cat ~/.ssh/id_rsa.pub
[/code]

 

This will output something like the following

[code language=”bash”]
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+U6uomKAd0lgP1g/pj6q44w599N8b9kVjdc1W5WDp0ciujFvIoe/ZwdyZVft2LnsWnPPypD0JsgZ7pe68kVyE3+NNOrfT6g6FImgKAZ585q/5OqRbCs8CiDjFaKPDk9bpy7Fl6IMnBNIde7dnw81LPtYr7k1CX6jgIYGu7yjGgWCLysEVTeON+x0JCqxFkMhjtcJFCMyjq5Mgjqm2JN/FoXgNiXrc3GQ08LfKpjKNpxPpJVoEgI/+AGk6yrGw4l4pQcRQQFh9yRJFslIBDp7ZOt02XB9jbMhgRwm8yAETwVYz18pI/c8PWtf++//84vHE5IY+uwiZF28GB5npaqHv [email protected]
[/code]

Copy the content. On the server, type the following as root.

[code language=”bash”]
su – saumyakswain
[/code]

This will log you in as the non-root user (the new user) which you want to login through public key. Once logged in, create a .ssh directory in the new user’s home and restrict its permissions.

[code language=”bash”]
mkdir ~/.ssh
chmod 700 ~/.ssh
[/code]

Create a file named authorized_keys using your favourite text editor in the .ssh directory.

[code language=”bash”]
nano ~/.ssh/authorized_keys
[/code]

Paste the contents of the public key which you copied form your local system into this file. Press “Ctrl+x” to exit. Press “y” when prompted to same. Now restrict access to this file by the following command.

[code language=”bash”]
chmod 700 ~/.ssh/authorized_keys
[/code]

Return to the root user by pressing Ctrl+d or the following command.

[code language=”bash”] exit [/code]

Disable Password Authentication

Now that we have configured public key authentication, it’s a good idea to disable password based authentication. As root, edit the sshd configuration file.

[code language=”bash”] sudo nano /etc/ssh/sshd_config [/code]

Find the line with “PasswordAuthentication”. Change it’s value to “no”.

[code language=””] PasswordAuthentication no [/code]

Exit the editor by pressing Ctrl+x. Press “y” to save.

Reload the configuration of the ssh daemon for the changes to take effect.

[code language=”bash”] systemctl reload ssh.service [/code]

Try logging in as the new user from a new terminal.

[code language=”bash”] ssh [email protected]_server_ip [/code]

Type a command with sudo.

[code language=”bash”] sudo tail /var/log/auth.log [/code]

Setup a Basic Firewall

A firewall restricts or allows a connection into or out of a server based on rules. UFW or Uncomplicated Firewall is one such utility which comes installed on Ubuntu Server 16.04. Different applications register their profiles with UFW during installation. We can activate these profiles to allow the application to communicate. To view the available application profiles, as non-root user type:

[code language=”bash”] sudo ufw app list [/code]

This should display OpenSSH as an output. Allow communication for OpenSSH by the following command.

[code language=”bash”] sudo ufw allow OpenSSH [/code]

Now enable ufw.

[code language=”bash”] sudo ufw enable [/code&amp;amp;amp;amp;amp;amp;lt;/pre&amp;amp;amp;amp;amp;amp;gt;
Type "y" and press Enter. Check status of ufw by typing:
&amp;amp;amp;amp;amp;amp;lt;pre&amp;amp;amp;amp;amp;amp;gt;[code language="bash"] sudo ufw status [/code]

When you install more applications like Nginx or Postfix, they will register their profile with ufw. You will need to allow their profiles through ufw before using them.