How to install Nginx (latest), MySQL, PHP 7.2 (LEMP stack) in Ubuntu 16.04

Work in Progress…

This tutorial is about installing a full LEMP stack for a later WordPress (Joomla, Drupal, …) installation. You’ll need a remote server (VPS or dedicated), this is not compatible with shared hosting. This guide does not cover the Linux-installation itself: Linux should already be installed on the server. Here is our “LEMP” stack:

  • Linux (Ubuntu 16.04 LTS minimal)
  • (E)NGINX (Mainline)
  • MySQL
  • PHP 7.2


  1. Connect to the server with SSH
  2. Change root password, create new user with sudo privileges
  3. Update packages
  4. Install NGnix
  5. Install a firewall
  6. Install MySQL
  7. Install PHP 7
  8. Install PHP latest (7.2)
  9. Install PhpMyAdmin
  10. Install Webmin
  11. Install a Let’s Encrypt certificate
  12. Install WordPress
  13. Migrate multisite to standalone site
  14. Install Apache and php modules for Total Cache
  15. Install VSFTPD

1. Connect to server via SSH

On Windows, download the free Putty utility. On Linux, use a terminal:
ssh root@your.server.ip.address -p22

Check your hoster for your servers IP-address and the port to connect.

Alternatively, use ssh keys instead of password:
SSH login without password using SSH keys

2. Change root password, create new user with sudo privileges

Change the root password:

This command changes the password for the current user, which is fine now as you are probably logged in as root.

Create a new user:
adduser username

Add sudo priviledges:
usermod -aG sudo username

3. Update packages

Starting with Ubuntu 16.04, no need to use apt-get anymore, apt is enough.

Update the list of available updates:
sudo apt update

Upgrade the current packages:
sudo apt upgrade

Or combine both in one line:
sudo apt update && sudo apt upgrade

Possible problem with locales (perl warning)

If you run into the following warning (frequent with Hetzner hosting):

perl: warning: Setting locale failed.
perl: warning: Falling back to a fallback locale ("en_US.UTF-8").
locale: Cannot set LC_ALL to default locale: No such file or directory

Check the following post for a solution:
Ubuntu: resolve the “perl: warning: Setting locale failed” problem

Now the server is ready to install LAMP. Two reference articles:

DigitalOcean: How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 16.04
Tecmint: How to Install LAMP with Apache, PHP 7 and MariaDB 10 on Ubuntu 16.04 Server

4. Install latest Nginx Mainline

Most tutorials want you to install the nginx version which comes with Ubuntu 16.04:

sudo apt update
sudo apt install nginx

Or combine both in one line:
sudo apt update && sudo apt install nginx

However, this version is quite old. It is preferable to install the latest “mainline” version from the servers:

echo "deb xenial nginx" | sudo tee -a /etc/apt/sources.list
echo "deb-src xenial nginx" | sudo tee -a /etc/apt/sources.list
wget -qO - | sudo apt-key add -
sudo apt update
sudo apt install nginx

The Nginx version from seems to be more up-to-date than the official ppa, which is much more recent than the “stock” Nginx version which comes with Ubuntu 16.04.

Check the Nginx status and version:
sudo service nginx status
nginx -v

Test Nginx in browser (may only work after setting up the firewall):

5. Install ufw firewall

Install a firewall:
sudo apt install ufw

Make sure the firewall will let through SSH connections (important!) and Apache traffic. Ufw has presets for both. Display the presets for these applications:
sudo ufw app list

To get more information on a profile, use:
sudo ufw app info "Nginx Full"

Allow OpenSSH and Apache connections:
sudo ufw allow OpenSSH
sudo ufw allow in "Nginx Full"

or as in Digital Oceans guide:

sudo ufw allow 'Nginx HTTP'
sudo ufw allow 'Nginx HTTPS'

If you install Nginx from the servers, there will be no preinstalled ufw rules for nginx. Then simply use:

sudo ufw allow http
sudo ufw allow https

Check if everything is ok:

sudo ufw status

Now that SSH is allowed, enable the Firewall (confirm with “y”):
sudo ufw enable

Activating Ufw Firewall on remote server

6. Install MySQL

Install MySQL with the following command:

sudo apt-get install mysql-server

The installation will ask you to set a “root” password – don’t use the same as your servers root password! Continue with the following command:


This command is explained in details in the excellent Digital Ocean guide by Brennen Bearnes:
How To Install Linux, Apache, MySQL, PHP (LAMP) stack on Ubuntu 16.04

Check whether MySQL server is running with the following command:

sudo service mysql status

Stop and start the MySQL server with:

sudo service mysql stop
sudo service mysql start

MySQL is installed, now it’s php’s turn.

7. Install PHP

Make sure which version of php you want to install. Google differences between version (i.e. 7.0, 7.1, 7.2, etc) and check compatibility with your WordPress addons.

Most guides will recommend installing the default php version which comes with Ubuntu (php 7.0):

sudo apt install php-fpm php-mysql

For later WordPress installation, install the following php modules:

sudo apt install php-gettext php-curl php-zip mcrypt php-gd php-mbstring php-mcrypt php-xmlrpc php-xml

Restart php-fpm for php modules to be activated:

sudo systemctl restart php7.0-fpm

Check if it works:

sudo service php7.0-fpm status


Install php 7.1 or 7.2

To install a newer php version (here we will go for 7.2), add Ondřej Surý’s ppa.

First install following package:
sudo apt install software-properties-common

Then add the ppa:
sudo add-apt-repository ppa:ondrej/php
sudo apt update

Now install php 7.2 (replace numbers for 7.1):
sudo apt install php7.2-fpm php7.2-mysql

For later WordPress installation, install the following php modules:
sudo apt install php7.2-curl php7.2-gd php7.2-mbstring php7.2-xmlrpc php7.2-xml php7.2-zip

Restart php-fpm for php modules to be activated:

sudo systemctl restart php7.2-fpm

Check if it works:

sudo service php7.2-fpm status

Check the DigitalOcean article to configure the php processor and Nginx.

Make upload of big files possible (in php AND nginx)

Change upload_max_filesize, post_max_size etc – IMPORTANT!

8. Install PhpMyAdmin in Ubuntu 16.04

Follow this guide to install PhpMyAdmin securely:
Digital Ocean: How To Install and Secure phpMyAdmin on Ubuntu 16.04

9. Install Webmin

Add Servername in Apache2conf

sudo nano /etc/apache2/apache2.conf

Add following line at the end:


Follow this guide to install webmin:
Digital Ocean: How To Install Webmin on Ubuntu 16.04

Don’t forget to allow the 1000 port with ufw:
sudo ufw allow webmin

10. Install a Let’sEncrypt certificate

Add the Server Name in Virtual host

List existing virtual hosts with:

apache2ctl -S

Add the server name in the defaut Apache virtual server (or set up a new virtual server for that purpose). Check the DigitalOcean guide for more info:
How To Set Up Apache Virtual Hosts on Ubuntu 16.04

What I did was keeping the default virtual host as is, just adding tho lines to the configuration file:

nano /etc/apache2/sites-enabled/000-default.conf


Restart Apache to apply changes:

sudo systemctl restart apache2

Add Servername in Apache2conf

If you didn’t do it yet, set a server name:

sudo nano /etc/apache2/apache2.conf

Add following line at the end:


Install Let’s encrypt

To be able to use add-apt-repository, install the following packages:

sudo apt-get install software-properties-common

Reference article:
Digital Ocean: How To Secure Apache with Let’s Encrypt on Ubuntu 16.04

To set up the cron job, first choose nano as standard editor: else you’ll have to edit with vi!


Then you can set up the cron job:

sudo crontab -e

43 4 * * 2 /usr/bin/certbot renew --quiet

Example: every Tuesday on 4:43

11. Install WordPress

Use this Digital Oceans guide to install WordPress:
How To Install WordPress with LAMP on Ubuntu 16.04

However, the following method for creating MySQL users and privileges is deprecated:

GRANT ALL ON wordpress.* TO 'wordpressuser'@'localhost' IDENTIFIED BY 'password';

User the following two lines instead:

CREATE USER 'jeffrey'@'localhost' IDENTIFIED BY 'mypass';
GRANT ALL ON db1.* TO 'jeffrey'@'localhost';

Check priviledges with:

show grants for 'jeffrey'@'%';

Permissions pour le dossier /var/www/html

Ne PAS utiliser:

sudo chown -R sammy:www-data /var/www/html


sudo chown -R www-data:www-data /var/www/html

Extract Multisite to standalone WordPress

Of course you should do a full backup of your old website. But there is more than that:

On the website you want to move:

  • Install the Widget Importer & Exporter Plugin to backup all widgets (else they won’t be migrated)
  • Deactivate Jetpack photon
  • Deactivate other plugins?
  • Deactivate permalinks (?)
  • Deactivate caching plugins

Follow the guide:
Envato tuts+: Moving WordPress: Moving a Site Out of a Multisite Network

Export SQL tables – Fix path and prefixes

Export SQL Files with phpMyAdmin, as shown in guide.

Once exported, replace occurences of subsite table prefixes and path in exported file:

/sites/4 remplacer par RIEN
eva_4_ remplacer par eva_

For big SQL dumps, use the command line sed tool:

sed -i 's/eva_4_/wp_/g' "dbvyeaia(3).sql"

For the path, use another sed separator:

sed -i 's_/sites/4__g' "dbvyeaia(3).sql"

Recover admin rights for any user:
wpbeginner: How to Add an Admin User to the WordPress Database via MySQL

Import SQL tables – Problems with too big files

Import SQL Files with phpMyAdmin.

If the SQL file is too big, modify the php.ini located in:

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

Change the following lines:

post_max_size = 8M
upload_max_filesize = 8M

Then restart Apache:

sudo /etc/init.d/apache2 restart
sudo service apache2 restart

Redirect domain name to IP to finish installation

Before the site goes live, you can change it locally through its ip address without being redirected to the old site.

Edit the hosts file on local computer (NOT remote server):

sudo nano /etc/hosts

Add the following line:

Redirect www to non-www domain

Edit the .htaccess file

sudo nano /var/www/html/.htaccess

Add the following block:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} ^www\.(.*)$ [NC]
RewriteRule ^(.*)$ http://%1/$1 [R=301,L]
# BEGIN WordPress

Before the site goes live

  • Change back hosts file edit on local computer (NOT remote server):

nano /etc/hosts

Remove the following line:

  • Change back php.ini, disallow too big files
  • Reactivate permalinks, photon, plugins

Install Apache modules for Total Cache

Install the apache modules mod_expires, mod_headers, mod_ext_filter

sudo a2enmod expires

sudo a2enmod headers

sudo a2enmod ext_filter

The restart Apache service:

sudo service apache2 restart

Install PHP modules for W3 Total Cache

DON’T do this:

sudo apt install memcached php-memcache

sudo service memcached restart

sudo update-rc.d memcached enable

Because it does not work? (or slows up your site!)

Install VSFTPD

sudo apt install vsftpd

sudo nano /etc/vsftpd.conf

Add or uncomment all these lines to vsftpd.conf:







Then allow these ports for ufw:

sudo ufw allow ftp-data

sudo ufw allow ftp

sudo ufw allow 2121:2142/tcp

Restart deamon:

sudo /etc/init.d/vsftpd restart

Note that the root user won’t be allowed to connect via FTP, as it is listed in /etc/ftpusers (list of users disallowed FTP access).

Try this if FTP does not work:

sudo ufw allow 990/tcp
(Not needed in my case)

Useful commands

sudo netstat -tlpn

Posted in Allgemein.

Post a comment