How to install a LEMP stack on Ubuntu 18.04

LEMP Tutorial on Ubuntu (How to install Linux, Nginx, PHP, MySQL)


This guide shows how to get a full LEMP software stack installed on Ubuntu 18.04. The LEMP stack can later be used to set up a CMS like WordPress, Joomla or Drupal.

There are tons of tutorials on this subject. The goal of this particular one is to be the most comprehensive and best documented guide on installing LEMP on Ubuntu. Please leave a comment if you have any additions or corrections.


  • A remote server (VPS or dedicated). Any DigitalOcean Droplet or Linode cloud server is also adapted. Even the smallest Vultr cloud server is capable of serving a high amount of requests (with proper Nginx FastCGI caching). These instructions are not compatible with shared hosting.
  • A fresh Ubuntu installation. This guide does not cover the Linux installation itself.

Too many spelling or grammatical errors?

The author of this article is French and German, and obviously not a native English speaker. Any correction will be gladly accepted. Please send an email to Libre Software - Contact for spellings Contact

One last thing: use the middle-click to paste

Before you copy and paste a lot of commands, make sure you do it the most efficient way. I have seen a lot of advanced Linux users being really inefficient doing basic copy and paste. The UNIX way to copy and paste is the following:

  1. select any text in any application to copy, and
  2. middle-click to paste.

Please note that selecting a text already does the copy. There is no need to actively copy via a menu or via Ctrl + C. This way of copy and pasting is by far the fastest. More, the paste buffer won’t interfere with the “normal” (menu or keyboard activated) copy and paste buffer. As a consequence, you can use two parallel copy and paste buffers on Linux.

Want to be even more efficient? The following Ubuntu documentation page gives even more uses of the middle-click:
Ubuntu Official Documentation » Middle-click

1. Prepare Ubuntu

In this tutorial, we’ll use Ubuntu 18.04 LTS. However, this guide should also work with previous Ubuntu versions. You can check your Linux version with the following command:

lsb_release -a

How to know which version of Linux or Ubuntu you're running (lsb_release -a)

1.1 Connect to server via SSH

On Windows, download the free Putty software. Though the official website looks like a relict of the 20th century, the software is a reference. On Linux, simply use a terminal:
ssh root@your.server.ip.address

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

1.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 newuser

Add sudo privileges to the newly created user (as a secondary group):
usermod -aG sudo newuser

Verify that the change was made:
id newuser

The id command should output something like this:
uid=1001(newuser) gid=1001(newuser) groups=1001(newuser),27(sudo)

If you want to know more about adding new and existing users to primary and secondary groups in Linux, check out this reference article:
Linux: Add User to Group (Primary/Secondary/New/Existing)

1.3 Update packages

Since 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

Frequent problem with locales (perl warning)

You may run into the following warning when installing or upgrading packages:

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

1.4 Set up automatic updates

If you don’t have time to update your server manually on a regular basis, it is recommended to set up automatic updates.

Follow this tutorial to enable automatic updates on Ubuntu:
How to set up automatic updates on Ubuntu Server 18.04

2. Install Nginx on Ubuntu 18.04

Nginx as a part of a LEMP stack

There are at least three common ways to install Nginx on Ubuntu:

  1. Install the default Nginx packages from the Ubuntu repositories (recommended).
  2. Install Nginx from the Nginx “Mainline” ppa.
  3. Install Nginx from the official repository.

The Nginx version from (3.) seems to be more up-to-date than the Nginx Mainline ppa (2.), which is mostly more recent than the “stock” Nginx version which comes with Ubuntu 18.04 (1.).

2.1 Install the default Nginx packages from the Ubuntu repositories (recommended)

Current version on Ubuntu 18.04: Nginx 1.14.0 (Released in April 2018).

This installation procedure is the easiest and most common. Use this one if you are unsure. Installing Nginx from the Ubuntu repositories has one drawback: the packages tend to get old quickly. For example, the repository version of Nginx in Ubuntu 16.04 is 1.10.3 (released January 2017).

sudo apt update
sudo apt install nginx

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

If you chose this installation method, skip points 2.2 and 2.3 and jump to 2.4 to test Nginx.

2.2 Install Nginx from the Nginx “Mainline” ppa

NGINX “Mainline” ppa on Launchpad:

Warning: The ppa does not currently support Ubuntu 18.04. Support for Bionic should be available soon.

Current “Mainline” ppa version: Nginx 1.15.0 (released April 2018).

There are two common use case for this ppa:
– The default repository version in Ubuntu 18.04 is not actual anymore, or
– Install a recent build of Nginx on old Ubuntu versions.

Add the repository with the following command:
sudo add-apt-repository ppa:nginx/development

NB: Ubuntu 18.04 is removing the need to run apt-get update after adding a repository, as it will run automatically after add-apt-repository.

Now install Nginx:
sudo apt install nginx

Skip point 2.3 to test Nginx.

2.3 Install Nginx from the official repository

Pre-Built Packages for Mainline version on

Warning: The repository does not currently support Ubuntu 18.04. Support for Bionic should be available soon.

This will get you the latest version of Nginx. Use this version if you are a pro and if you really need the most actual Nginx build, as it may lack some Ubuntu specific integration and tweaks.

Download and add the PGP key to authenticate the Nginx repository signature:
wget -qO - | sudo apt-key add -

Append the repositories to the end of the /etc/apt/sources.list file:

echo "deb bionic nginx" | sudo tee -a /etc/apt/sources.list

echo "deb-src bionic nginx" | sudo tee -a /etc/apt/sources.list

Update and install:
sudo apt update && sudo apt install nginx

2.4 Test Nginx

Check the Nginx system service status and version with the following command:
sudo service nginx status

Stop and start Nginx:
sudo service nginx stop
sudo service nginx start

Or simply restart:
sudo service nginx restart

Nginx status – Nginx on Ubuntu 18.04 as part of a LEMP stack installation

Should you use systemctl or service to manage system services?

Are you wondering what the difference between systemctl and service could be, and which one you should be using?

  • Short answer: for basic tasks, use service. For advenced system management, prefer systemctl (or initctl or the /etc/init.d script on other distributions).
  • Long answer: read the first answer on Ask Ubuntu:
    Difference between Systemctl and Service
Nginx version and http test

Enter this command if you want to know which version of Nginx you are running:
nginx -v

Test Nginx in your browser:

This should display the standard Nginx welcome page in your browser:

Test Nginx

5. Install ufw firewall

Firewall on Ubuntu (UFW - uncomplicated firewall)

Install ufw:
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 the Digital Ocean 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

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

Check the firewall status:
sudo ufw status

UFW Firewall as part of a LEMP deployment on Linux

4. Install MariaDB/MySQL

MySQL vs MariaDB in a LEMP stack

MariaDB vs MySQL

Should you choose MySQL or MariaDB for your LEMP server? I couldn’t find any reliable benchmarks comparing the performance of MySQL vs MariaDB as part of a LEMP stack. Chances are high that the performance is comparable. In this tutorial, we’ll cover both MySQL and MariaDB – it’s up to you to choose.

4.1 Install MariaDB

MariaDB is a fork of MySQL, leaded by some of the original developers of MySQL. MariaDB can be used as a high compatible drop-in replacement of MySQL.

MariaDB is used by Wikimedia and the Mozilla foundation – amongst others. Some of the biggest Linux distribution have switched to MariaDB, such as Debian, Red Hat Enterprise Linux, openSUSE/SLES, …

Install MariaDB with the following command:
sudo apt install mariadb-server

4.2 Install MySQL

We’ll use the default MySQL packages from the Ubuntu repositories.

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!

4.3 Configure MariaDB/MySQL

Continue with the following command, which is valid both for MariaDB and MySQL:
sudo mysql_secure_installation

If you use MariaDB, a root password does not exist and you will be prompted to create a new one (just press enter at the first question and set a new password). If you use MySQL, you probably already created a root password during the mysql-server package installation.

Here are the recommended answers to the next questions:

  • Remove anonymous users? [Y/n]: Y
  • Disallow root login remotely? [Y/n]: Y
  • Remove test database and access to it? [Y/n]:  Y
  • Reload privilege tables now? [Y/n]:  Y

Restart MariaDB/MySQL (this command works for both):
sudo service mysql restart

Check whether MariaDB/MySQL server is running with the following command:
sudo service mysql status
↑ this command also works for MariaDB! ↑

MariaDB or MySQL status - LEMP on Ubuntu

Stop and start the MariaDB/MySQL server with:
sudo service mysql stop
sudo service mysql start

5. Install PHP

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

If you are migrating your CMS from Ubuntu 16.04 to 18.04, expect problems! The default php version which comes with Ubuntu 18.04 is PHP 7.2, whereas Ubuntu 16.04 came with PHP 7.0 by default.

PHP 7.2 is relatively recent and many CMS plugins are likely to suffer from incompatibilities. If you plan to migrate WordPress to a newer PHP version, you may want to try the PHP Compatibility Checker addon: PHP Compatibility Checker

5.1 Install PHP 7.2

sudo apt install php-fpm php-mysql

If you plan to install WordPress on this server, install the following php modules:
sudo apt install php-gettext php-curl php-zip mcrypt php-gd php-mbstring php-xmlrpc php-xml

Restart php-fpm for php modules to be activated:
sudo service php7.2-fpm restart

Check if it works:
sudo service php7.2-fpm status

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

5.2 Install PHP 5.6, 7.0 or 7.1 / downgrade PHP

First, you may want to consider how long the PHP version you want to install will be supported. Here are the security support deadlines for “older” PHP versions:

  • PHP 5.6: until December 31, 2018
  • PHP 7.0: until December 3, 2018
  • PHP 7.1: until December 1, 2019

More information on PHP support: official “Supported Version” page.

To install an older php version, add Ondřej Surý’s ppa. This PPA is well known, up to date, and is considered as safe to use.

To be able to use add-apt-repository, install the 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 (replace numbers with chosen version):
sudo apt install php7.1-fpm php7.1-mysql

Make the downgraded version of PHP the default version (replace with 5.6 or 7.0 if needed):
sudo update-alternatives --set php /usr/bin/php7.1

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

Restart php-fpm for php modules to be activated:
sudo service php7.1-fpm restart

Check if it works:
sudo service php7.1-fpm status

Configure Nginx to use PHP

At this point, Nginx doesn’t know it should use php-fpm to process .php files.

Open the default Nginx server block configuration file:
sudo nano /etc/nginx/sites-available/default

Add index.php to the list:
index index.php index.html index.htm index.nginx-debian.html;

Uncomment the following four lines by removing the # at the beginning of each line:

location ~ \.php$ {
   include snippets/fastcgi-php.conf;
  fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;

↑ Important: change the penultimate line to match your php version!

And finally, uncomment these three lines:
location ~ /\.ht {
   deny all;

The server block configuration file should now look like this (except a few comments I removed for clarity):

Configure Nginx to work with PHP in Ubuntu 18.04 as part of a LEMP stack

Test the configuration:
nginx -t

Reload Nginx:
sudo service nginx reload

Allow big files upload in Nginx and PHP

Increase upload limit in Nginx

The standard upload size limit in Nginx is 1 MB. This limit is probably too low for mosts use cases including any CMS. Too large files will generate a 413 (Request Entity Too Large) error.

The maximum upload size is defined by the client_max_body_size directive. Edit the Nginx configuration file:
sudo nano /etc/nginx/nginx.conf

Type Ctrl + W to search for the client_max_body_size variable. On a fresh installation it probably isn’t defined at all. Modify or add the following line inside the http block:
client_max_body_size 20M;

Increase upload max size in Nginx (client_max_body_size)

Adapt to your needs, for example 10M, 100M, 500M or 2G. Set the size to 0 to disable any checking of the upload size (not recommended!). Use m or M for Megabites, G or g for Gigabytes. More details on Nginx’ configuration file measurement units: Configuration file measurement units

Note that the client_max_body_size variable can also be set in the server and location contexts.

Test the configuration:
nginx -t

Reload Nginx:
sudo service nginx reload

Increase file upload limit in PHP

Change upload_max_filesize, post_max_size etc – IMPORTANT!

6. Install PhpMyAdmin in Ubuntu 18.04

Run the following command to install phpMyAdmin:
sudo apt install phpmyadmin

When confronted to the following dialog, hit ⭾ Tab and ⏎ Enter to bypass the prompt:

MySQL configuration on LEMP and Ubuntu 18.04

The next dialog will ask if you want to “Configure database for phpmyadmin with dbconfig-common?” Press ⏎ Enter to choose “Yes”.

When asked to, enter the database root password that you configured during the secure MySQL installation.

Then create a symbolic link from the phpMyAdmin files to the Nginx document root directory:
sudo ln -s /usr/share/phpmyadmin /var/www/html/phpmyadmin

Check if the symlink is in place:
ls -al /var/www/html

Restart PHP (choose or adapt to your version):
sudo service php7.2-fpm restart
sudo service php7.1-fpm restart
sudo service php7.0-fpm restart

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

Uninstall phpMyAdmin on Ubuntu 18.04

Warning: this post has been updated until here. Following content is a draft.

Remove the phpmyadmin package and all packages which have been installed together with it:

sudo apt remove dbconfig-common dbconfig-mysql libjs-jquery libjs-sphinxdoc libjs-underscore php php-phpseclib php7.2 phpmyadmin

Remove the symbolic link in the Nginx document root directory:
sudo rm /usr/share/nginx/html/phpmyadmin

Restart PHP (choose or adapt to your version):
sudo service php7.2-fpm restart

7. Install a Let’sEncrypt certificate

Install Let’s encrypt

Follow this reference article:
Digital Ocean: How To Secure Nginx 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

8. Install WordPress

Use this Digital Oceans guide to install WordPress:
How To Install WordPress with LEMP 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 databasename.* TO 'jeffrey'@'localhost';

Check priviledges with:

show grants for 'jeffrey'@'localhost';

Connect to FTP via SSH

Create a new FTP user:
adduser ftpuser

If you plan to install WordPress or another CMS, you may want to add this user to the www-data group. To ensure files updoaded by ftpuser will have the www-data group label by default, add www-data as a primary group:
sudo usermod -g www-data ftpuser

By Johannes Eva, January 2017 – May 2018

Posted in Allgemein.


  1. On some blogs, I see sudo service mysql start for starting mariadb server whereas on other sites I see the command as sudo systemctl start mariadb.service.

    I want to know what’s the difference and which works correctly on Ubuntu 18.04?

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.