Install a LEMP Stack on Ubuntu 16.04
Updated by Linode Written by Linode
What is a LEMP Stack?
The LAMP stack (Linux, Apache, MariaDB, and PHP) is a popular server configuration for developing and hosting web applications. The four components of the stack are not tightly coupled, making it possible to substitute your preferred technologies. The LEMP stack is a common variant in which the Apache web server is replaced by NGINX.
Before You Begin
- You will need root access to the system, or a user account with
sudo
privilege. - Set your system’s hostname.
- Update your system.
Installation
NGINX
These steps install NGINX Mainline on Ubuntu from NGINX Inc’s official repository. For other distributions, see the NGINX admin guide. For information on configuring NGINX for production environments, see our Getting Started with NGINX series.
Open
/etc/apt/sources.list
in a text editor and add the following line to the bottom. ReplaceCODENAME
in this example with the codename of your Ubuntu release. For example, for Ubuntu 18.04, named Bionic Beaver, insertbionic
in place ofCODENAME
below:- /etc/apt/sources.list
-
1
deb http://nginx.org/packages/mainline/ubuntu/ CODENAME nginx
Import the repository’s package signing key and add it to
apt
:sudo wget http://nginx.org/keys/nginx_signing.key sudo apt-key add nginx_signing.key
Install NGINX:
sudo apt update sudo apt install nginx
Ensure NGINX is running and and enabled to start automatically on reboot:
sudo systemctl start nginx sudo systemctl enable nginx
MariaDB
Install the MariaDB server and MySQL/MariaDB-PHP support. You may be prompted to set a root password during installation.
sudo apt install mariadb-server php7.0-mysql
Run the mysql_secure_installation script:
sudo mysql_secure_installation
If you were not prompted to create a MySQL root user password when installing MariaDB, answer the script Y to set one.
Answer Y at the following prompts:
- Remove anonymous users?
- Disallow root login remotely?
- Remove test database and access to it?
- Reload privilege tables now?
Log in to MariaDB’s SQL shell. Enter the
root
user’s password when prompted.mysql -u root -p
Create a test database and user with access permission. Replace
testdb
andtestuser
with appropriate names for your setup. Replacepassword
with a strong password.CREATE DATABASE testdb; CREATE USER 'testuser' IDENTIFIED BY 'password'; GRANT ALL PRIVILEGES ON testdb.* TO 'testuser'; quit
PHP
Install the PHP FastCGI Processing Manager, which will bring in the core PHP dependencies:
sudo apt install php7.0-fpm
Tell PHP to only accept URIs for files that actually exist on the server. This mitigates a security vulnerability where the PHP interpreter can be tricked into allowing arbitrary code execution if the requested
.php
file is not present in the filesystem. See this tutorial for more information about this vulnerability.sudo sed -i 's/;cgi.fix_pathinfo=1/cgi.fix_pathinfo=0/g' /etc/php/7.0/fpm/php.ini
Ownership of PHP’s listening UNIX sockets is set to
www-data
by default, but they need to match the user and group NGINX is running as. If you installed NGINX from the NGINX repository as done above, NGINX will be using thenginx
user and group. Change thelisten
variables inwww.conf
to that:sudo sed -i 's/listen.owner = www-data/listen.owner = nginx/g' /etc/php/7.0/fpm/pool.d/www.conf sudo sed -i 's/listen.group = www-data/listen.group = nginx/g' /etc/php/7.0/fpm/pool.d/www.conf
Set an NGINX Site Configuration File
Create a root directory where the site’s content will live. Replace example.com with your site’s domain.
sudo mkdir -p /var/www/example.com/
Disable the default site configuration provided with the package as an example. Or if you have no use for it, delete it.
sudo mv /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.disabled
Website configuration files should be kept in
/etc/nginx/conf.d/
. Create a configuration file for your site. Again replace example.com with your site’s domain.- /etc/nginx/conf.d/example.com.conf
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
server { listen 80 default_server; listen [::]:80 default_server; server_name example.com www.example.com; root /var/www/example.com; index index.html; location / { try_files $uri $uri/ =404; } location ~* \.php$ { fastcgi_pass unix:/run/php/php7.0-fpm.sock; include fastcgi_params; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_param SCRIPT_NAME $fastcgi_script_name; } }
Here’s a breakdown of the
server
block above:NGINX is listening on port 80 for incoming connections to example.com or www.example.com.
The site is served out of
/var/www/example.com/
and it’s index page (index.html
) is a simple.html
file. If your index page will use PHP, substituteindex.php
forindex.html
.try_files
tells NGINX to verify that a requested file or directory actually exist in the site’s root filesystem before further processing the request. If it does not, a404
is returned.location ~* \.php$
means that NGINX will apply this configuration to all .php files (file names are not case sensitive) in your site’s root directory, including any subdirectories containing PHP files.The
*
in the~* \.php$
location directive indicates that PHP file names are not case sensitive. This can be removed if you prefer to enforce letter case.fastcgi_pass
specifics the UNIX socket where PHP listens for incoming connections from other local processesinclude fastcgi_params
tells NGINX to process a list offastcgi_param
variables at/etc/nginx/fastcgi_params
.The
fastcgi_param
directives contain the location (relative to the site’s root directory) and file naming convention of PHP scripts to be served when called by NGINX.
Test the LEMP Stack
Restart PHP and reload the NGINX configuration:
sudo systemctl restart php7.0-fpm sudo nginx -s reload
Create a test page to verify NGINX can render PHP and connect to the MySQL database. Replace the
"testuser"
and"password"
fields with the MySQL credentials you created above.- /var/www/example.com/test.php
-
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
<html> <head> <h2>LEMP Stack Test</h2> </head> <body> <?php echo '<p>Hello,</p>'; // Define PHP variables for the MySQL connection. $servername = "localhost"; $username = "testuser"; $password = "password"; // Create a MySQL connection. $conn = mysqli_connect($servername, $username, $password); // Report if the connection fails or is successful. if (!$conn) { exit('<p>Your connection has failed.<p>' . mysqli_connect_error()); } echo '<p>You have connected successfully.</p>'; ?> </body> </html>
Go to
http://example.com/test.php
in a web browser. It should report that You have connected successfully. If you see an error message or if the page does not load at all, re-check your configuration.Remove the test file once the stack is verified to be working correctly:
sudo rm /var/www/example.com/test.php
Join our Community
Find answers, ask questions, and help others.
This guide is published under a CC BY-ND 4.0 license.