Tutorial

How To Install Linux, Nginx, MySQL, PHP (LEMP stack) in Ubuntu 16.04

How To Install Linux, Nginx, MySQL, PHP (LEMP stack) in Ubuntu 16.04
Not using Ubuntu 16.04?Choose a different version or distribution.
Ubuntu 16.04

Introduction

The LEMP software stack is a group of software that can be used to serve dynamic web pages and web applications. This is an acronym that describes a Linux operating system, with an Nginx web server. The backend data is stored in the MySQL database and the dynamic processing is handled by PHP.

In this guide, we will demonstrate how to install a LEMP stack on an Ubuntu 16.04 server. The Ubuntu operating system takes care of the first requirement. We will describe how to get the rest of the components up and running.

Prerequisites

Before you complete this tutorial, you should have a regular, non-root user account on your server with sudo privileges. You can learn how to set up this type of account by completing our Ubuntu 16.04 initial server setup.

Once you have your user available, sign into your server with that username. You are now ready to begin the steps outlined in this guide.

Step 1: Install the Nginx Web Server

In order to display web pages to our site visitors, we are going to employ Nginx, a modern, efficient web server.

All of the software we will be using for this procedure will come directly from Ubuntu’s default package repositories. This means we can use the apt package management suite to complete the installation.

Since this is our first time using apt for this session, we should start off by updating our local package index. We can then install the server:

  1. sudo apt-get update
  2. sudo apt-get install nginx

On Ubuntu 16.04, Nginx is configured to start running upon installation.

If you have the ufw firewall running, as outlined in our initial setup guide, you will need to allow connections to Nginx. Nginx registers itself with ufw upon installation, so the procedure is rather straight forward.

It is recommended that you enable the most restrictive profile that will still allow the traffic you want. Since we haven’t configured SSL for our server yet, in this guide, we will only need to allow traffic on port 80.

You can enable this by typing:

  1. sudo ufw allow 'Nginx HTTP'

You can verify the change by typing:

  1. sudo ufw status

You should see HTTP traffic allowed in the displayed output:

Output
Status: active To Action From -- ------ ---- OpenSSH ALLOW Anywhere Nginx HTTP ALLOW Anywhere OpenSSH (v6) ALLOW Anywhere (v6) Nginx HTTP (v6) ALLOW Anywhere (v6)

With the new firewall rule added, you can test if the server is up and running by accessing your server’s domain name or public IP address in your web browser.

If you do not have a domain name pointed at your server and you do not know your server’s public IP address, you can find it by typing one of the following into your terminal:

  1. ip addr show eth0 | grep inet | awk '{ print $2; }' | sed 's/\/.*$//'

This will print out a few IP addresses. You can try each of them in turn in your web browser.

As an alternative, you can check which IP address is accessible as viewed from other locations on the internet:

  1. curl -4 icanhazip.com

Type one of the addresses that you receive in your web browser. It should take you to Nginx’s default landing page:

http://server_domain_or_IP

Nginx default page

If you see the above page, you have successfully installed Nginx.

Step 2: Install MySQL to Manage Site Data

Now that we have a web server, we need to install MySQL, a database management system, to store and manage the data for our site.

You can install this easily by typing:

  1. sudo apt-get install mysql-server

You will be asked to supply a root (administrative) password for use within the MySQL system.

The MySQL database software is now installed, but its configuration is not exactly complete yet.

To secure the installation, we can run a simple security script that will ask whether we want to modify some insecure defaults. Begin the script by typing:

  1. mysql_secure_installation

You will be asked to enter the password you set for the MySQL root account. Next, you will be asked if you want to configure the VALIDATE PASSWORD PLUGIN.

Warning: Enabling this feature is something of a judgment call. If enabled, passwords which don’t match the specified criteria will be rejected by MySQL with an error. This will cause issues if you use a weak password in conjunction with software which automatically configures MySQL user credentials, such as the Ubuntu packages for phpMyAdmin. It is safe to leave validation disabled, but you should always use strong, unique passwords for database credentials.

Answer y for yes, or anything else to continue without enabling.

VALIDATE PASSWORD PLUGIN can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD plugin?

Press y|Y for Yes, any other key for No:

If you’ve enabled validation, you’ll be asked to select a level of password validation. Keep in mind that if you enter 2, for the strongest level, you will receive errors when attempting to set any password which does not contain numbers, upper and lowercase letters, and special characters, or which is based on common dictionary words.

There are three levels of password validation policy:

LOW    Length >= 8
MEDIUM Length >= 8, numeric, mixed case, and special characters
STRONG Length >= 8, numeric, mixed case, special characters and dictionary                  file

Please enter 0 = LOW, 1 = MEDIUM and 2 = STRONG: 1

If you enabled password validation, you’ll be shown a password strength for the existing root password, and asked you if you want to change that password. If you are happy with your current password, enter n for “no” at the prompt:

Using existing password for root.

Estimated strength of the password: 100
Change the password for root ? ((Press y|Y for Yes, any other key for No) : n

For the rest of the questions, you should press Y and hit the Enter key at each prompt. This will remove some anonymous users and the test database, disable remote root logins, and load these new rules so that MySQL immediately respects the changes we have made.

At this point, your database system is now set up and we can move on.

Step 3: Install PHP for Processing

We now have Nginx installed to serve our pages and MySQL installed to store and manage our data. However, we still don’t have anything that can generate dynamic content. We can use PHP for this.

Since Nginx does not contain native PHP processing like some other web servers, we will need to install php-fpm, which stands for “fastCGI process manager”. We will tell Nginx to pass PHP requests to this software for processing.

We can install this module and will also grab an additional helper package that will allow PHP to communicate with our database backend. The installation will pull in the necessary PHP core files. Do this by typing:

  1. sudo apt-get install php-fpm php-mysql

Configure the PHP Processor

We now have our PHP components installed, but we need to make a slight configuration change to make our setup more secure.

Open the main php-fpm configuration file with root privileges:

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

What we are looking for in this file is the parameter that sets cgi.fix_pathinfo. This will be commented out with a semi-colon (;) and set to “1” by default.

This is an extremely insecure setting because it tells PHP to attempt to execute the closest file it can find if the requested PHP file cannot be found. This basically would allow users to craft PHP requests in a way that would allow them to execute scripts that they shouldn’t be allowed to execute.

We will change both of these conditions by uncommenting the line and setting it to “0” like this:

/etc/php/7.0/fpm/php.ini
cgi.fix_pathinfo=0

Save and close the file when you are finished.

Now, we just need to restart our PHP processor by typing:

  1. sudo systemctl restart php7.0-fpm

This will implement the change that we made.

Step 4: Configure Nginx to Use the PHP Processor

Now, we have all of the required components installed. The only configuration change we still need is to tell Nginx to use our PHP processor for dynamic content.

We do this on the server block level (server blocks are similar to Apache’s virtual hosts). Open the default Nginx server block configuration file by typing:

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

Currently, with the comments removed, the Nginx default server block file looks like this:

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.html index.htm index.nginx-debian.html;

    server_name _;

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

We need to make some changes to this file for our site.

  • First, we need to add index.php as the first value of our index directive so that files named index.php are served, if available, when a directory is requested.
  • We can modify the server_name directive to point to our server’s domain name or public IP address.
  • For the actual PHP processing, we just need to uncomment a segment of the file that handles PHP requests by removing the pound symbols (#) from in front of each line. This will be the location ~\.php$ location block, the included fastcgi-php.conf snippet, and the socket associated with php-fpm.
  • We will also uncomment the location block dealing with .htaccess files using the same method. Nginx doesn’t process these files. If any of these files happen to find their way into the document root, they should not be served to visitors.

The changes that you need to make are in red in the text below:

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    root /var/www/html;
    index index.php index.html index.htm index.nginx-debian.html;

    server_name server_domain_or_IP;

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

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

    location ~ /\.ht {
        deny all;
    }
}

When you’ve made the above changes, you can save and close the file.

Test your configuration file for syntax errors by typing:

  1. sudo nginx -t

If any errors are reported, go back and recheck your file before continuing.

When you are ready, reload Nginx to make the necessary changes:

  1. sudo systemctl reload nginx

Step 5: Create a PHP File to Test Configuration

Your LEMP stack should now be completely set up. We can test it to validate that Nginx can correctly hand .php files off to our PHP processor.

We can do this by creating a test PHP file in our document root. Open a new file called info.php within your document root in your text editor:

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

Type or paste the following lines into the new file. This is valid PHP code that will return information about our server:

/var/www/html/info.php
<?php
phpinfo();

When you are finished, save and close the file.

Now, you can visit this page in your web browser by visiting your server’s domain name or public IP address followed by /info.php:

http://server_domain_or_IP/info.php

You should see a web page that has been generated by PHP with information about your server:

PHP page info

If you see a page that looks like this, you’ve set up PHP processing with Nginx successfully.

After verifying that Nginx renders the page correctly, it’s best to remove the file you created as it can actually give unauthorized users some hints about your configuration that may help them try to break in. You can always regenerate this file if you need it later.

For now, remove the file by typing:

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

Conclusion

You should now have a LEMP stack configured on your Ubuntu 16.04 server. This gives you a very flexible foundation for serving web content to your visitors.

Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.

Learn more about our products

About the authors

Still looking for an answer?

Ask a questionSearch for more help

Was this helpful?
 
79 Comments
Leave a comment...

This textbox defaults to using Markdown to format your answer.

You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!

This comment has been deleted

    Can someone suggest a cloud-config script for the above? If not, I will work on creating one as I think this would be useful and more tweakable than the DO-provided One-Click LEMP (not available yet as I’m commenting)

    Use this one for one click install:

    https://github.com/mirzazeyrek/lemp-wordpress-stack

    I love this script. All you need is sit back and relax.

    Search for Easy Engine

    Nice guide… waiting for wordpress + LEMP

    Justin Ellingwood
    DigitalOcean Employee
    DigitalOcean Employee badge
    April 25, 2016

    @iamkingsleyf: Good timing! I just published it here.

    Great guide!

    This comment has been deleted

      I’d be interested to hear how to use PHP 5.6 on 16.04.

      Guides exist elsewhere online, but I’m unsure how using php-fpm with Nginx afterwards fits in. Will it work?

      Maybe you’d recommend sticking 14.04 if PHP 5.x support is needed with Nginx?

      I did upgrade from ubuntu 15, I run virtual host where previously I keep all site configuration at /etc/php5/fpm/pool.d/ , after upgrade I moved those configuration to /etc/php/7.0/fpm/pool.d/ But when I restart php7.0-fpm service, It loaded but inactive…

      Result from service php7.0-fpm status php7.0-fpm.service - The PHP 7.0 FastCGI Process Manager Loaded: loaded (/lib/systemd/system/php7.0-fpm.service; enabled; vendor preset: enabled) Active: inactive (dead) since Thu 2016-04-28 10:17:16 AEST; 4s ago Process: 8774 ExecStart=/usr/sbin/php-fpm7.0 --nodaemonize --fpm-config /etc/php/7.0/fpm/php-fpm.conf (code Process: 8764 ExecStartPre=/usr/lib/php/php7.0-fpm-checkconf (code=exited, status=0/SUCCESS) Main PID: 8774 (code=exited, status=0/SUCCESS)

      Problem solved, apparently not enough resource. Now I’m wondering if we can run php7.0 for certain apps, and php5.6 for other apps…

      Whats the difference between using:

      fastcgi_pass unix:/run/php/php7.0-fpm.sock;
      
      

      and

       fastcgi_pass 127.0.0.1:9000;
      

      on Nginx server blocks

      Is one better than the other?

      Justin Ellingwood
      DigitalOcean Employee
      DigitalOcean Employee badge
      May 12, 2016

      @luismuzquiz: Those lines specify how Nginx should try to connect to the backend processor (in this case PHP-FPM).

      The first line that you mention uses a Unix socket. This is basically a specialized file that let’s applications on the same host pass data between one another. Since Unix sockets can only be used for communication within a single host, they’re often considered to be superior to network communication from a security standpoint and also usually has a better performance profile. By default, Ubuntu’s PHP-FPM installation is configured to use a Unix socket, so that is why we select that line.

      The second line is a connecting over a network or internet socket. It is bound to the local loopback device, so it should only be accessible to other applications on the same host as well. Different dynamic processors are configured to listen on different sockets, ports, etc. out of the box, so this second line is configured in order to accommodate the default listening port of a different backend processor (PHP-CGI I think).

      If you wanted to, you could configure these connections to be whatever ports or sockets you want, but the default server block file is set up to match the defaults of some of its more commonly used backend processors. Since we’re using PHP-FPM in this guide, we use the Unix socket. Hope that helps!

      thanks 4 your explanation @jellingwood =)

      great and clear explanation and tutorial @jellingwood !! thank you! <3

      If you are trying to install JOOMLA or WP you will need to:

      sudo apt-get install php7.0-xml
      

      Good point! Toom me some time to figure out this, because at least Jetpack not working without. Also GD or Imagick needed for pics. Other tutorial proposes ‘apt-get install php7.0-fpm php7.0-mysql php7.0-curl php7.0-gd php7.0-json php7.0-mcrypt php7.0-opcache php7.0-xml’. Not sure if all of these are needed or not?

      and if you a are using K2 2.7 you may need to install php7.0-gd so you can upload images through K2 component

      nice guide when i want to see info.php nginx shows 502 Bad Gateway! what is this and why there is? how can i fix it? thank for the help!

      This comment has been deleted

        Please make sure that you have uncommented the line fastcgi_pass unix:/run/php/php7.0-fpm.sock; So the section should look like:

        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;
        
        

        Please also make sure that your php version is correct. In my case it is 7.2 so nginx location block should look like this.

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

        I had this problem too, everything was configured properly. Well, not exactly. After reinstalling my Ubuntu Server 16.04 few times, and running several test on vbox, i finally discovered that for some strange and odd reason the php-fm listen address is different (it was perfect on vbox installs, doing the same on server it was not working). Check /etc/php/7.0/fpm/pool.d/www.conf file and look for the line “listen”. In my case it is: listen = /run/php/php7.0-fpm.sock

        Now if you look at the default nginx config for php, it is probably /var/run/php7.0-fpm.sock. Adjust this line to /run/php/php7.0-fpm.sock in nginx, restart nginx and there you go, you have a working php.

        The default nginx config might be different since I was using the ppa stable nginx to install nginx, not the ubuntu repo.

        Thank you:)

        Everything is working as it should after your tutorial. Thanks for the write-up!

        Hi,

        So I am having issues getting NGINX to work after installing it, when NOT using a domain name e.g. just use IP to access it. This issue is occurring both on a local Raspberry Pi and on a DO droplet.

        First off, after I installed NGINX, i COULD see the “Welcome to NGINX” test page, but as soon as I made changes to sites-available by deleting default from sites-enabled I can get my own page to work.

        Basically, I added my own root dir: /var/www/test - 755 for directories, 644 files test:test for user/group

        In /etc/nginx/sites-available/test:

        server {
                listen 80 default_server;
        
                root /var/www/test;
        
                # Add index.php to the list if you are using PHP
                index.html;
        
                server_name _;
        
                location / {
                        # First attempt to serve request as file, then
                        # as directory, then fall back to displaying a 404.
                        try_files $uri $uri/ =404;
                }
        }
        

        I added this to sites-enabled.

        But nothing shows up when I enter the droplets IP in. The same IP that gave me the “Welcome to NGINX” test page.

        I have setup countless droplets successfully when using a domain name, but in this case I wish to not use a domain name at all and nothing is working.

        Any ideas to get the web server to work without a using a domain?

        Also I tried using curl -I http://111.111.111.111 I get:

        curl: (7) Failed to connect to 111.111.111.111 port 80: Connection refused
        

        figured it out:

        Hey,

        I just came accross an issue. Doesn’t matter if its a local setup or one with a domain name.

        When you create a symbolic frpom sites-available to sites-enabled you have to use the whole path to each location.

        e.g. you can’t

        cd /etc/nginx/sites-available/
        ln -s monitor ../sites-enabled/
        

        It has to be:

        ln -s  /etc/nginx/sites-available/monitor  /etc/nginx/sites-enabled/
        

        Thank you. It helps me a lot :)

        Stuck on http://mydomain.com/info.php thing.

        My /etc/nginx/sites-available/default is: server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.php index.html index.htm index.nginx-debian.html; server_name mydomain.com; return 301 https://$server_name$request_uri; location / { try_files $uri $uri/ =404; } location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } location ~ /.ht { deny all; } location ~ /.well-known { allow all; } }

        server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; include snippets/ssl-mydomain.com.conf; include snippets/ssl-params.conf; }

        When trying to connect https://mydomain.com/info.php get “404 Not Found”, but log show me: [error]: *4 open() “/usr/share/nginx/html/info.php” failed (2: No such file or directory)

        Seems like nginx treats /usr/share/nginx/html as documents root directory instead of /var/www/html :(

        Same problem. Did you find solution?

        Wondering why you do not suggest modifying the Unix user/group of processes and changing the default www-data to the user credentials created on Ubuntu?

        user = www-data
        group = www-data
        

        Great article.Seeing your first page in a VPS it’s so NICE!

        Hi Justin,

        What an excellent guide. Thanks for putting the right level of details in it. In following the steps I was able to get my LEMP stack up and running.

        Keep up the good work.

        Hats off to you guys for providing great tutorials like this! Thanks for it!

        Has anyone been able to come up with a caching strategy for Ubunt 16.04, Nginx 1.10 & PHP 7? Seems like every guide online is for Ubuntu 14.04, Nginx 1.8 and PHP 5.X.

        Have gone through about 10 different guides, but none give full object caching, full page caching, and the ability to clear the cache, ideally via the Wordpress Nginx Helper plugin (which is maintained by rtCamp, who, as far as I’m aware, has all of his scripts setup for old ubuntu, old nginx and old php).

        Trying to get all of this working with HTTP/2, which means I can’t run Ubuntu 14.04 (due to some requirements from Chrome), or Nginx 1.8, as it does not support HTTP/2 (far as I’m aware).

        So, some guidance on getting something in place for these newer versions with HTTP/2 would be extraordinarily helpful, and much appreciated.

        Hello,

        I would like to know if you have ever considered MariaDB over Mysql? Or would you stick with Mysql?

        Just wanting to know as I am considering changing to MariaDB as I heard it was a lot faster than Mysql?

        Thanks

        Everything is working as it should after your tutorial. Thanks for the write-up!

        Hi,

        So I am having issues getting NGINX to work after installing it, when NOT using a domain name e.g. just use IP to access it. This issue is occurring both on a local Raspberry Pi and on a DO droplet.

        First off, after I installed NGINX, i COULD see the “Welcome to NGINX” test page, but as soon as I made changes to sites-available by deleting default from sites-enabled I can get my own page to work.

        Basically, I added my own root dir: /var/www/test - 755 for directories, 644 files test:test for user/group

        In /etc/nginx/sites-available/test:

        server {
                listen 80 default_server;
        
                root /var/www/test;
        
                # Add index.php to the list if you are using PHP
                index.html;
        
                server_name _;
        
                location / {
                        # First attempt to serve request as file, then
                        # as directory, then fall back to displaying a 404.
                        try_files $uri $uri/ =404;
                }
        }
        

        I added this to sites-enabled.

        But nothing shows up when I enter the droplets IP in. The same IP that gave me the “Welcome to NGINX” test page.

        I have setup countless droplets successfully when using a domain name, but in this case I wish to not use a domain name at all and nothing is working.

        Any ideas to get the web server to work without a using a domain?

        Also I tried using curl -I http://111.111.111.111 I get:

        curl: (7) Failed to connect to 111.111.111.111 port 80: Connection refused
        

        figured it out:

        Hey,

        I just came accross an issue. Doesn’t matter if its a local setup or one with a domain name.

        When you create a symbolic frpom sites-available to sites-enabled you have to use the whole path to each location.

        e.g. you can’t

        cd /etc/nginx/sites-available/
        ln -s monitor ../sites-enabled/
        

        It has to be:

        ln -s  /etc/nginx/sites-available/monitor  /etc/nginx/sites-enabled/
        

        Thank you. It helps me a lot :)

        Stuck on http://mydomain.com/info.php thing.

        My /etc/nginx/sites-available/default is: server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.php index.html index.htm index.nginx-debian.html; server_name mydomain.com; return 301 https://$server_name$request_uri; location / { try_files $uri $uri/ =404; } location ~ .php$ { include snippets/fastcgi-php.conf; fastcgi_pass unix:/run/php/php7.0-fpm.sock; } location ~ /.ht { deny all; } location ~ /.well-known { allow all; } }

        server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; include snippets/ssl-mydomain.com.conf; include snippets/ssl-params.conf; }

        When trying to connect https://mydomain.com/info.php get “404 Not Found”, but log show me: [error]: *4 open() “/usr/share/nginx/html/info.php” failed (2: No such file or directory)

        Seems like nginx treats /usr/share/nginx/html as documents root directory instead of /var/www/html :(

        Same problem. Did you find solution?

        Wondering why you do not suggest modifying the Unix user/group of processes and changing the default www-data to the user credentials created on Ubuntu?

        user = www-data
        group = www-data
        

        Great article.Seeing your first page in a VPS it’s so NICE!

        Hi Justin,

        What an excellent guide. Thanks for putting the right level of details in it. In following the steps I was able to get my LEMP stack up and running.

        Keep up the good work.

        Hats off to you guys for providing great tutorials like this! Thanks for it!

        Has anyone been able to come up with a caching strategy for Ubunt 16.04, Nginx 1.10 & PHP 7? Seems like every guide online is for Ubuntu 14.04, Nginx 1.8 and PHP 5.X.

        Have gone through about 10 different guides, but none give full object caching, full page caching, and the ability to clear the cache, ideally via the Wordpress Nginx Helper plugin (which is maintained by rtCamp, who, as far as I’m aware, has all of his scripts setup for old ubuntu, old nginx and old php).

        Trying to get all of this working with HTTP/2, which means I can’t run Ubuntu 14.04 (due to some requirements from Chrome), or Nginx 1.8, as it does not support HTTP/2 (far as I’m aware).

        So, some guidance on getting something in place for these newer versions with HTTP/2 would be extraordinarily helpful, and much appreciated.

        Hello,

        I would like to know if you have ever considered MariaDB over Mysql? Or would you stick with Mysql?

        Just wanting to know as I am considering changing to MariaDB as I heard it was a lot faster than Mysql?

        Thanks

        I have followed everything but whenever I go to http://myipaddress/info.php It basically downloads the file with codes. Please help me why it happens. Thanks in advance.

        Can you tell me why Url friendly does not work (mod_rewrite)? My laravel route does not work, just open the homepage. Thank you!

        Hi I did solve it. Just replaced try_files $uri $uri//index.php?$query_string; with try_files $uri $uri/ /index.php$is_args$args; ** This correct??**

        $ sudo apt-get install php-fpm php-mysql Reading package lists… Done Building dependency tree Reading state information… Done E: Unable to locate package php-fpm E: Unable to locate package php-mysql

        FYI – When I install using sudo apt-get install nginx, I don’t get the same installation as you’re showing here. My default config file and HTML files are in /etc/nginx/conf.d/default and /usr/share/nginx/html respectively. There’s something about that particular package that makes running a PHP app or WordPress problematic. I got errors about the snippets directory not found, which didn’t exist.

        If I use sudo apt-get install nginx-full, the installation looks much more like what you’re showing in the tutorial. I was able to follow every step and copy/paste the config and it worked perfectly.

        Took most of the day to figure out nginx-full was the path to success.

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        October 3, 2016

        @chrisf: Hello. I’m not sure what would make the nginx installation use a different path. My two guesses would be that you’ve either enabled the Nginx project repositories, which are overriding the default Ubuntu repositories or that you are using a different version of Ubuntu. In Ubuntu 16.04, the default nginx package pulls in nginx-core by default, which uses the paths outlined in this guide. I’m sorry to hear that you had so much trouble though. I’m glad that you figured out something that worked for you.

        Thanks, Jellingwood. I had previously used EasyEngine to install the LEMP stack and WordPress. I had it all ripped out but hadn’t noticed the incorrect packages. Learning a lot about packages lately. Thanks again.

        Just to clarify, using nginx-full does work and using it led me to discover the package issue I wasn’t aware of.

        Guys, I made some video tutorial. https://www.youtube.com/watch?v=9VoUj57AUNc Open for suggestions and opinions. Don’t judge me hard, first tutorial:)

        What is the main difference between following this guide and using “One-click-apps” for installing LEMP on 16.04?

        Thanks for the great tutorial.

        I followed the initial server setup, which included enabling the ufw firewall. Do I also need to allow connections for mysql, which I will be using for wordpress.

        If so, how do I do this and what rules would I need to add?

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        November 21, 2016

        @rejkpp If your web server and database server are installed on the same machine (like this guide demonstrates), you do not need to allow firewall access since local connections are allowed by default.

        If you have your database server installed on a separate machine from your web server, you’d need to open up port 3306 on the database server, like this:

        1. ufw allow 3306

        Hope that helps.

        Yes, that certainly helps, Many thanks :)

        when running the script for sql security , i get access denied , here’s how my console looks like : $ sudo mysql_secure_installation

        Securing the MySQL server deployment.

        Enter password for user root: Error: Access denied for user ‘root’@‘localhost’ (using password: YES)

        I am certain that i have used correct password for root. I even changed the root password and tried with the new password but gives me same access denied message.

        Please let me know how i can fix it.

        Also, i followed the initial server setup guide from support documentation where it says to change /etc/ssh/sshd_config file on the line for password authentication. This is how my sshd_config file looks like :

        #PasswordAuthentication no
        

        Thanks in advance !!

        The root password here is referring to the Mysql root password and is not the root user password that set in the initial server setup guide.

        Hope this help! :)

        Thanks!! that was pretty stupid of me :) this was a very nice guide. I am done with the setup and just waiting for my domain name to resolve to new DO droplet IP so i can start the next steps of migrating data. Meanwhile is there any good place i can look at for migrating a wordpress website being hosted on hostinghq to DO servers? Also, i installed LEMP stack on my Ubuntu, is it a problem if the site currently uses Apache ? thank you in advance !!

        For me the installation is always stuck at

        Renaming removed key_buffer and myisam-recover options (if present)
        

        With phpMyAdmin, setting the following will incorrectly redirect you to / after login:

        cgi.fix_pathinfo=0
        

        Anyone else getting error “Unable to locate package php-fpm”? Running Debian jessie 8.6 with all updates applied?

        Hi,

        What happens if I’m still using PHP5 as seen here

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

        May I know what am I missing here as currently I’m not able to run any php file?

        Any advice is much appreciated!

        Thanks!

        I’ve encountered some problems with installing nginx. Maybe some of you have been encountering the same, but I get a generic Error.

        I had discovered that if apache2 is running nginx won’t install for ubuntu 16. If you just stop the service it will install:

        service apache2 stop

        The package is called php5-mysql in Ubuntu, not php-mysql.

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        January 18, 2017

        @4allilyxa This tutorial was written for Ubuntu 16.04. Since Ubuntu 16.04 does not ship with PHP 5, the package is named php7.0-mysql. There is a generic php-mysql package in Ubuntu 16.04 that points to the latest version of the package to ease future compatibility. If you are using a different version of Ubuntu, consider following this guide for Ubuntu 14.04 or this guide for Ubuntu 12.04. I hope that helps.

        On ‘nginx.conf’ it should be better to:

        server_tokens off;

        to avoid a full show of nginx version; please if you have idea to completely clear out server tokens (also on soft 404 pages) please update the article or reply to my post.

        Thank you.

        Nginx is running under the user www-data so this should be taken into account when you create a user for accessing the web data

        Any idea of why any changes that I make to my php.ini file doesn’t work? I followed this guide step by step. When I make any change to /etc/php/7.0/fpm/php.in, next I check if the new value using phpinfo(); on a test page but is not working at all.

        Thanks!

        Does this guide include the enabling of caching? I see that fastcgi is mentioned, but I’m unsure if that is full micro-caching which is supposed to be very beneficial to site performance.

        After typing this: sudo mysql_secure_installation

        I’m getting this:

        Error: Access denied for user 'root'@'localhost' (using password: YES)
        

        **Please help… **

        This tutorial wouldn’t work on Wordpress, on all links excluding index.php you’ll get a Nginx 404 Error. change the: try_files $uri $uri/ =404; with: try_files $uri $uri/ /index.php$is_args$args;

        There is no fastcgi-php.conf file available in Nginx folder. What to do then?

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        March 6, 2017

        @neolivz The fastcgi-php.conf file should be installed if you are using Ubuntu’s default repositories to get Nginx and are running Ubuntu 16.04. If you are using a different distribution or installing Nginx from another source, these instructions might not work.

        That being said, the fastcgi.conf file is almost identical to the fastcgi_params file. The only difference is that it also includes this line:

        fastcgi.conf
        fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
        . . .
        

        You can include the fastcgi_params file instead if you add that line to the location block, like this:

        /etc/nginx/sites-available/default
        . . .
            location ~ \.php$ {
                include fastcgi_params;
                fastcgi_param  SCRIPT_FILENAME    $document_root$fastcgi_script_name;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
            }
        . . .
        

        Hope that helps.

        Oh God thank you so much. I had just wasted hours trying to make it work with the instructions from the PHP website. Your instructions here worked flawlessly for me! I am so grateful, now I can finally start coding.

        Hello, everyone.

        In the end i don’t get the info.php showing beautifully like the image by Zend Engine, but it downloads the info.php to my notebook without showing anything in browser. I followed every step very carefully and getting all the expected results. The most difficult part for me was to generate the ssh keys for root and user. But everything went ok… after one week trying and becoming a droplet killer. This one i don’t want to destroy… please, help. :)

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        March 17, 2017

        @Areku Sorry to hear you’re having problems. First off, I’d double check that you’re using Ubuntu 16.04 specifically. Ubuntu is fairly similar from release to release, but there can be some specific differences that impact the configuration you need (LEMP is one of those cases). If you’re on Ubuntu 16.04, great. If not, one of the tutorials here will probably help you out more.

        Alright, assuming you’re running Ubuntu 16.04, If the file is downloading instead of executing your PHP file, the issue is probably with the Nginx configuration. Open up the /etc/nginx/sites-available/default file again:

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

        Inside, double check that the value of server_name is set to your server’s IP address or domain name. The value should be whatever domain or address you expect to use in your web browser. This is important because it is how Nginx determines whether to use the settings in this file when it receives a request. You can also input multiple values, like this:

        /etc/nginx/sites-available/default
        server_name example.com www.example.com 203.0.113.5;
        

        Next, I’d look at the location block for processing PHP. If you’ve installed Nginx from Ubuntu’s default repositories (not from another source, like the Nginx project’s repositories, then this location block should work as-is, without any editing:

        /etc/nginx/sites-available/default
            location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php7.0-fpm.sock;
            }
        

        Since there’s nothing custom here, it’s probably best to copy and paste it. There’s not much else to look at after that. Save and close the file.

        Remember to test your configuration and reload it. Test it by typing:

        1. sudo nginx -t

        If no errors are shown, restart Nginx to utilize the new configuration:

        1. sudo systemctl restart nginx

        After that, retry in your browser. Hopefully, something changed and it’ll work this time.

        My php-fpm7.0 is always under highload even without traffic. What is the problem? 30071 www-data 20 0 474076 10820 3276 R 47.0 2.2 73:25.69 php-fpm7.0

        Thanks!

        Yes, my droplet is 16.04. But i killed other droplets before and they were 14.04. I don’t know if destroying droplets has implications on building new ones.

        About the /etc/nginx/sites-available/default Indid, i missed to write my domain in the line the first time i went thru. The other issue mentioned was all right. I checked the syntax. I reloaded nginx after modifying the line. But even after giving multiples values in the suggested line, the behavior of the browser is the same.

        http://radha.org.br/info.php

        I would like to upgrade PHP7.0 to PHP7.1, you provide upgrade steps?

        Thanks, Arjun

        I only want to add that cgi.fix_pathinfo=0 isn’t needed.

        Yo can read why at: https://serverfault.com/questions/627903/is-the-php-option-cgi-fix-pathinfo-really-dangerous-with-nginx-php-fpm

        Can I translate your essay into Chinese on my personal website?

        Justin Ellingwood
        DigitalOcean Employee
        DigitalOcean Employee badge
        April 27, 2017

        @LewisLiu Yes, you can definitely do that as long as you adhere to the licensing terms.

        All of the content on the DigitalOcean community site is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International (CC BY-NC-SA 4.0) license. Basically, the license says that you’re free to copy and modify as long as it’s not used for commercial purposes, you give attribution, and you license any changes under the same terms. I hope that helps!

        I wrote a tutorial step by step to setup an environment for Laravel5 with Nginx, MariaDB, PHP7 on Ubuntu 17.04. https://medium.com/@robertodev/how-to-setup-your-lemp-server-on-ubuntu-17-04-6910b18a3679

        If i want to set up everything for php 5.6, is something change? I also have nginx 1.10 version and default file looks little bit different than yours. Is it normal?

        i got this error in “sudo nginx -t”: [ nginx: [emerg] open() “/etc/nginx/snippets/fastcgi-php.conf” failed (2: No such file or directory) in /etc/nginx/sites-enabled/default:55 nginx: configuration file /etc/nginx/nginx.conf test failed ] i changed the line,

        • include snippets/fastcgi-php.conf; with
        • include fastcgi_params;

        and everything good.

        i didn’t find out what is the error for? anyone knows?

        Hi, got problem to isntall PHP, when I put command sudo apt-get install php-fpm php-mysql,
        my terminal told me this:

        php-fpm : Depends: php7.0-fpm but it is not going to be installed
        E: Unable to correct problems, you have held broken packages.```
        
        How can I fix it? a little help here, guys? many thanks! 
        
        

        I was running into a error where I’d get a blank page response at step 4, and eventually found out that I needed the following line to get it working:

        fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        

        For reference, Avoiding Blank PHP Responses After Upgrading, and NGINX with PHP-FPM, Blank page

        Thanks. It helps me out.

        Excellent, short and helpful guide - thank you. I just followed this on my Ubuntu 16.04 droplet with no issues whatsoever.

        The tutorial is great but there is no mention of the option to install it directly when creating a new droplet.

        Of course there are other things to do after that and it would be great to have a tutorial going depper on LEMP usage after direct droplet install.

        All the best from France !

        Hi, What would be the difference between the one click LEMP install and the one you propose here? Thx,

        Hi, I recently figured out a nice emerging package which eases this entire tutorial in a single command.

        Check: https://github.com/santoshbaggam/stacker

        I feel this could be a helpful tool!

        how to setup server blocks with nodejs app as root with wordpress as child?

        location /{ }

        location /blog{ }

        tnx…x :|

        Straight forward, and concise! Thank you!

        I get the following error:

        Client with the currently selected authenticator does not support any combination of challenges that will satisfy the CA.
        

        Hi, I’m not able to install MySQL,

        Actually I have First Install Nginx & Then Do the SSL…

        You can Check it Here - https://refernloot.com/

        Now I want to install wordpress but getting error at mysql installation…

        Please Help Me… Here

        Hi, can I ask a question?

        when to restart php-fpm? or should i restart it everytime I deploy my laravel app?

        tnx. :D

        pls update to php 7.2 like "fastcgi_pass unix:/run/php/php7.2-fpm.sock; " instead of fastcgi_pass unix:/run/php/php7.0-fpm.sock; and “sudo systemctl restart php7.2-fpm” instead of “sudo systemctl restart php7.0-fpm”

        Hello Justin Ellingwood

        First of all I would like to thank you for writing such an article as it helped to install LEMP in very easy way as well as helped in configuring PHP processor in an effective way. Article is well documented. I was unable to install phpmyadmin with nginx as server. But this article serves as base for achieving the aim. Thanks a lot again for sharing such valuable information in an structured way.

        With Regards Sanpreet Singh

        solution for the “502 bad gateway” if the server dons’t read php files:

        when modfing the “/etc/nginx/sites-available/default” file make sure to write the correct php version at the line:

        fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

        if version of php instaled was the 7.2, then:

        fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;

        what is 502 bad gateway

        i create info.php and run then got 502 error

        Deberian de tener mas cuidado con las reglas UFW ya que muchos utilizan conexion por ssh y esto queda bloqueado con el tutorial antes visto, si va a hacer esto asegurese de habilitar el ssh sudo ufw allow ssh y si se esta utlizando un puerto personalizado sudo ufw allow 2222/tcp

        How to I add a fork of an existing gitlab project to my newly created LEMP stack?

        This is great guide but need update,

        The easiest way installing LEMP stack on Ubuntu/Debian you could use LEMPer stack installer

        sudo apt install git && git clone -q https://github.com/joglomedia/LEMPer.git && cd LEMPer && cp -f .env.dist .env && sudo ./install.sh
        

        Source : https://github.com/joglomedia/LEMPer

        Try DigitalOcean for free

        Click below to sign up and get $200 of credit to try our products over 60 days!

        Sign up

        Join the Tech Talk
        Success! Thank you! Please check your email for further details.

        Please complete your information!

        Become a contributor for community

        Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.

        DigitalOcean Documentation

        Full documentation for every DigitalOcean product.

        Resources for startups and SMBs

        The Wave has everything you need to know about building a business, from raising funding to marketing your product.

        Get our newsletter

        Stay up to date by signing up for DigitalOcean’s Infrastructure as a Newsletter.

        New accounts only. By submitting your email you agree to our Privacy Policy

        The developer cloud

        Scale up as you grow — whether you're running one virtual machine or ten thousand.

        Get started for free

        Sign up and get $200 in credit for your first 60 days with DigitalOcean.*

        *This promotional offer applies to new accounts only.