Installing Nginx with PHP 7 and MySQL 5.7 (LEMP) on Ubuntu 16.04 LTS

Nginx (pronounced "engine x") is a free, open-source, high-performance HTTP server. Nginx is known for its stability, rich feature set, simple configuration, and low resource consumption. This tutorial shows how you can install Nginx on an Ubuntu 16.04 server with PHP 7 support (through PHP-FPM) and MySQL 5.7 support (LEMP = Linux + nginx (pronounced "engine x") + MySQL + PHP).


1 Preliminary Note

In this tutorial, I use the hostname with the IP address These settings might differ for you, so you have to replace them where appropriate.

I'm running all the steps in this tutorial with root privileges, so make sure you're logged in as root:

sudo -s


2 Installing MySQL 5.7

In order to install MySQL, we run:

apt-get -y install mysql-server mysql-client

You will be asked to provide a password for the MySQL root user - this password is valid for the user [email protected] as well as [email protected], so we don't have to specify a MySQL root password manually later on:

New password for the MySQL "root" user: <-- yourrootsqlpassword
Repeat password for the MySQL "root" user: <-- yourrootsqlpassword


To secure the database server and remove  the anonymous user and test database, run the mysql_secure_installation command.


You will be asked these questions:

[email protected]:~# mysql_secure_installation

Securing the MySQL server deployment.

Enter password for user root: <-- Enter the MySQL root password

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: <-- Press y if you want this function or press Enter otherwise.
Using existing password for root.
Change the password for root ? ((Press y|Y for Yes, any other key for No) : <-- Press enter

... skipping.
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production

Remove anonymous users? (Press y|Y for Yes, any other key for No) : <-- y

Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) : <-- y

By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production

Remove test database and access to it? (Press y|Y for Yes, any other key for No) : <-- y
- Dropping test database...

- Removing privileges on test database...

Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) : <-- y

All done!

MySQL is secured now.

3 Installing Nginx

In case that you have installed Apache2 already, then remove it first with these commands & then install nginx:

service apache2 stop
update-rc.d -f apache2 remove
apt-get remove apache2

Nginx is available as a package for Ubuntu 16.04 which we can install.

apt-get -y install nginx

Start nginx afterwards:

service nginx start

Type in your web server's IP address or hostname into a browser (e.g., and you should see the following page:

The Ubuntu Nginx default page.

The default nginx document root on Ubuntu 16.04 is /var/www/html.


4 Installing PHP 7

We can make PHP work in nginx through PHP-FPM (PHP-FPM (FastCGI Process Manager) is an alternative PHP FastCGI implementation with some additional features useful for sites of any size, especially busier sites) which we install as follows:

apt-get -y install php7.0-fpm

PHP-FPM is a daemon process (with the init script php7.0-fpm) that runs a FastCGI server on the socket /run/php/php7.0-fpm.sock.


5 Configuring nginx

The nginx configuration is in /etc/nginx/nginx.conf which we open now:

nano /etc/nginx/nginx.conf

The configuration is easy to understand (you can learn more about it here: and here:

First (this is optional) adjust the keepalive_timeout to a reasonable value:

    keepalive_timeout   2;

The virtual hosts are defined in server {} containers. The default vhost is defined in the file /etc/nginx/sites-available/default - let's modify it as follows:

nano /etc/nginx/sites-available/default

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

# SSL configuration
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
# Note: You should disable gzip for SSL traffic.
# See:
# Read up on ssl_ciphers to ensure a secure configuration.
# See:
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
# include snippets/snakeoil.conf;

root /var/www/html;

# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.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;

# pass the PHP scripts to FastCGI server listening on
location ~ \.php$ {
include snippets/fastcgi-php.conf;

# With php7.0-cgi alone:
# fastcgi_pass;
# 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;
} [...]

server_name _; makes this a default catchall vhost (of course, you can as well specify a hostname here like

root /var/www/html; means that the document root is the directory /var/www/html.

The important part for PHP is the location ~ \.php$ {} stanza. Uncomment it to enable it.

Now save the file and reload nginx:

service nginx reload

Next open /etc/php/7.0/fpm/php.ini...

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

... and set cgi.fix_pathinfo=0:

; cgi.fix_pathinfo provides *real* PATH_INFO/PATH_TRANSLATED support for CGI.  PHP's
; previous behaviour was to set PATH_TRANSLATED to SCRIPT_FILENAME, and to not grok
; what PATH_INFO is.  For more information on PATH_INFO, see the cgi specs.  Setting
; this to 1 will cause PHP CGI to fix its paths to conform to the spec.  A setting
; of zero causes PHP to behave as before.  Default is 1.  You should fix your scripts

Reload PHP-FPM:

service php7.0-fpm reload

Now create the following PHP file in the document root /var/www/html:

nano /var/www/html/info.php


Now we call that file in a browser (e.g.

PHP Info on Ubuntu with Nginx.

As you see, PHP 7 is working, and it's working through FPM/FastCGI, as shown in the Server API line. If you scroll further down, you will see all modules that are already enabled in PHP. MySQL is not listed there which means we don't have MySQL support in PHP yet.


6 Getting MySQL Support In PHP 7

To get MySQL support in PHP, we can install the php7.0-mysql package. It's a good idea to install some other PHP modules as well as you might need them for your applications. You can search for available PHP modules like this:

apt-cache search php7.0

Pick the ones you need and install them like this:

apt-get -y install php7.0-mysql php7.0-curl php7.0-gd php7.0-intl php-pear php-imagick php7.0-imap php7.0-mcrypt php-memcache  php7.0-pspell php7.0-recode php7.0-sqlite3 php7.0-tidy php7.0-xmlrpc php7.0-xsl php7.0-mbstring php-gettext

APCu is an extension for the PHP Opcache module that comes with PHP 7, it adds some compatibility features for software that supports the APC cache (e.g. Wordpress cache plugins).

APCu can be installed as follows:

apt-get -y install php-apcu

Now reload PHP-FPM:

service php7.0-fpm reload

Now reload in your browser and scroll down to the modules section again. You should now find lots of new modules there, including the MySQL module:

The PHP Modules have been installed.


7 Making PHP-FPM use a TCP Connection

By default PHP-FPM is listening on the socket /var/run/php/php7.0-fpm.sock. It is also possible to make PHP-FPM use a TCP connection. To do this, open /etc/php/7.0/fpm/pool.d/www.conf...

nano /etc/php/7.0/fpm/pool.d/www.conf

... and make the listen line look as follows:

;listen = /var/run/php5-fpm.sock
listen =

This will make PHP-FPM listen on port 9000 on the IP (localhost). Make sure you use a port that is not in use on your system.

Then reload PHP-FPM:

php7.0-fpm reload

Next go through your nginx configuration and all your vhosts and change the line fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; to fastcgi_pass;, e.g. like this:

nano /etc/nginx/sites-available/default

        location ~ \.php$ {
include snippets/fastcgi-php.conf;

# With php7.0-cgi alone:
# With php7.0-fpm:
# fastcgi_pass unix:/run/php/php7.0-fpm.sock;
} [...]

Finally, reload nginx:

service nginx reload

That's it. The Nginx LEMP server is installed. 


Share this page:

Suggested articles

12 Comment(s)

Add comment


From: Couik


I followed all instruction.

My server is on in less than 5 minutes :)


Thanks very much



From: mirec

this tutorial leads to "502 Bad Gateway" on Ubuntu 15.10

From: efero

fix 502

Your configuration may differ somewhat. Look for a block beginning with location ~ \.php$ {, and a line that looks something like fastcgi_pass unix:/var/run/php5-fpm.sock;. Change this to use unix:/var/run/php/php7.0-fpm.sock.

  server { listen 80 default_server; listen [::]:80 default_server ipv6only=on; root /var/www/html; index index.php index.html index.htm; server_name server_domain_name_or_IP; location / { try_files $uri $uri/ =404; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; } location ~ \.php$ { try_files $uri =404; fastcgi_split_path_info ^(.+\.php)(/.+)$; fastcgi_pass unix:/var/run/php/php7.0-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } }

From: Zotrob Chackli

This sounds more like a LIMP server

From: Thor

Thanks for this really great tutorial, I have a question:

Is the last step (7) is optional? To configure PHP-FPM to listen on TCP?



From: Adam

Yeah why do all these tutorials tell people to set FPM to TCP? its very strange. People please use the socket.. no idea why on a single server the overhead of TCP could be a benefit.

From: sagar

2002 - No such file or directory — The server is not responding (or the local server's socket is not correctly configured).


 mysqli_real_connect(): (HY000/2002): No such file or directory

From: jhosepgonzalez

[email protected]:/home/desarollo/ahorasi# apt-get -y install php7.0-fpmLeyendo lista de paquetes... HechoCreando árbol de dependencias       Leyendo la información de estado... HechoE: No se ha podido localizar el paquete php7.0-fpmE: No se pudo encontrar ningún paquete con la expresión regular [email protected]:/home/desarollo/masseq#

From: acasado86

Very useful!

I would only add one thing.

 # Add index.php to the list if you are using PHP index index.php index.html index.htm index.nginx-debian.html;

From: vladimir kosyagen

feature request: put a date in your articles because without it, noone knows whether this info is actual or deprecated

From: till

Dates do not matter much for tutorials, tutorials are not news. I could write a tutorial for a 10 year old Ubuntu versions 10 years ago and I can write for it today, do you think that an article for a 10 year old OS would work on today's Ubuntu versions just because it was written today? No, it won't work. What really matters is for which Ubuntu version an article was written as that ensures that it will work for this Ubuntu version now and in many years in the exact same way. Take a look at the headline of the article, it shows the exact Ubuntu version (16.04) this article is made for, so this article will work for the version mentioned in the headline (16 = year 2016 and 04 = april) tells you also that the article must be written after that date.

From: dj steve bee



php7.0-fpm reload


did not work.. had to do:


/etc/init.d/php7.0-fpm restart



at the end I got:

"Job for nginx.service failed because the control process exited with error code.See "systemctl status nginx.service" and "journalctl -xe" for details."

then did:


$ sudo nginx -t


nginx: [emerg] "fastcgi_pass" directive is duplicate in /etc/nginx/sites-enabled/default:57


nginx: configuration file /etc/nginx/nginx.conf test failed


had to undo that last step by commenting:




in order to get the restart to work.

great tut btw! got me unstuck from a different one I had started with elsewhere!