This article covers a version of Ubuntu that is no longer supported. If you are currently operate a server running Ubuntu 12.04, we highly recommend upgrading or migrating to a supported version of Ubuntu:
Reason: Ubuntu 12.04 reached end of life (EOL) on April 28, 2017 and no longer receives security patches or updates. This guide is no longer maintained.
See Instead:
This guide might still be useful as a reference, but may not work on other Ubuntu releases. If available, we strongly recommend using a guide written for the version of Ubuntu you are using. You can use the search functionality at the top of the page to find a more recent version.
LEMP stack is a group of open source software to get web servers up and running. The acronym stands for Linux, nginx (pronounced Engine x), MySQL, and PHP. Since the server is already running Ubuntu, the linux part is taken care of. Here is how to install the rest.
The steps in this tutorial require the user to have root privileges. You can see how to set that up in the Initial Server Setup Tutorial in steps 3 and 4.
Throughout this tutorial we will be using apt-get as an installer for all the server programs. On May 8th, 2012, a serious php vulnerability was discovered, and it is important that we download all of the latest patched software to protect the virtual private server.
Let's do a thorough update.
sudo apt-get update
MySQL is a powerful database management system used for organizing and retrieving data
To install MySQL, open terminal and type in these commands:
sudo apt-get install mysql-server php5-mysql
During the installation, MySQL will ask you to set a root password. If you miss the chance to set the password while the program is installing, it is very easy to set the password later from within the MySQL shell.
Once you have installed MySQL, we should activate it with this command:
sudo mysql_install_db
Finish up by running the MySQL set up script:
sudo /usr/bin/mysql_secure_installation
The prompt will ask you for your current root password.
Type it in.
Enter current password for root (enter for none): OK, successfully used password, moving on...
Then the prompt will ask you if you want to change the root password. Go ahead and choose N and move on to the next steps.
It’s easiest just to say Yes to all the options. At the end, MySQL will reload and implement the new changes.
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 environment. Remove anonymous users? [Y/n] y ... Success! 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? [Y/n] y ... Success! 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 environment. Remove test database and access to it? [Y/n] y - Dropping test database... ... Success! - Removing privileges on test database... ... Success! Reloading the privilege tables will ensure that all changes made so far will take effect immediately. Reload privilege tables now? [Y/n] y ... Success! Cleaning up...
Once you're done with that you can finish up by installing PHP.
Once MySQL is all set up, we can move on to installing nginx on the VPS.
echo "deb http://ppa.launchpad.net/nginx/stable/ubuntu $(lsb_release -sc) main" | sudo tee /etc/apt/sources.list.d/nginx-stable.list sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys C300EE8C sudo apt-get update sudo apt-get install nginx
nginx does not start on its own. To get nginx running, type:
sudo service nginx start
You can confirm that nginx has installed an your web server by directing your browser to your IP address.
You can run the following command to reveal your VPS's IP address.
ifconfig eth0 | grep inet | awk '{ print $2 }'
To install PHP-FPM, open terminal and type in these commands. We will configure the details of nginx and php details in the next step:
sudo apt-get install php5-fpm
sudo nano /etc/php5/fpm/php.ini
Find the line, cgi.fix_pathinfo=1, and change the 1 to 0.
cgi.fix_pathinfo=0
If this number is kept as 1, the php interpreter will do its best to process the file that is as near to the requested file as possible. This is a possible security risk. If this number is set to 0, conversely, the interpreter will only process the exact file path—a much safer alternative. Save and Exit.
We need to make another small change in the php5-fpm configuration.Open up www.conf:
sudo nano /etc/php5/fpm/pool.d/www.conf
Find the line, listen = 127.0.0.1:9000, and change the 127.0.0.1:9000 to /var/run/php5-fpm.sock.
listen = /var/run/php5-fpm.sock
Save and Exit.
Restart php-fpm:
sudo service php5-fpm restart
Open up the default virtual host file.
sudo nano /etc/nginx/sites-available/default
The configuration should include the changes below (the details of the changes are under the config information):
UPDATE: Newer Ubuntu versions create a directory called 'html' instead of 'www' by default. If /usr/share/nginx/www does not exist, it's probably called html. Make sure you update your configuration appropriately.
[...] server { listen 80; root /usr/share/nginx/www; index index.php index.html index.htm; server_name example.com; location / { try_files $uri $uri/ /index.html; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/www; } # pass the PHP scripts to FastCGI server listening on the php-fpm socket location ~ \.php$ { try_files $uri =404; fastcgi_pass unix:/var/run/php5-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } [...]
Here are the details of the changes:
Save and Exit
We can quickly see all of the details of the new php configuration.
To set this up, first create a new file:
sudo nano /usr/share/nginx/www/info.php
Add in the following line:
<?php phpinfo(); ?>
Then Save and Exit.
Restart nginx
sudo service nginx restart
You can see the nginx and php-fpm configuration details by visiting http://youripaddress/info.php
Your LEMP stack is now set up and configured on your virtual private server.
After installing LEMP, you can Install WordPress, go on to do more with MySQL (A Basic MySQL Tutorial) or Install phpMyAdmin, Create an SSL Certificate, or Install an FTP Server.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
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!
“Uncomment the correct lines in “location ~ .php$ {“ section” —
Can you Give little eloboration on this. What settings needs to uncomment. I am getting. 502 bat gateway error. whil accessing a PHP page.
Thanks in advance
My bad. Typo… You can delete my comments. it worked.
No problem, glad you got it working =]
Hello,
I configured my servet just like this but my server is not behaving as expected when I try to access a URL that doesn’t exist.
If I try to access http://myserver/3i1idaosdj (a file that does not exist), I get a 500 Internal Server Error.
If I try to access http://myserver/3i1idaosdj.php (a file that does not exist and the URL ends with .php), I get a message saying “No input file specified”.
Accessing the error log, I got the following message:
2012/08/08 03:18:45 [error] 6699#0: *1 rewrite or internal redirection cycle while internally redirecting to “/index.html”, client: my ip, server: localhost, request: “GET /3i1idaosdj HTTP/1.1”, host: “my server ip”
Also, I configured the 404 error page in /etc/nginx/sites-available/default, via:
error_page 404 /404.html;
And 404.html is properly placed in the website folder. Why this is not working?
This comment has been deleted
In the nginx config make sure you updated: server_name example.com;
And replaced example.com with your actual domain name and then test it through the web.
If you just have an IP and not a domain name you can use that as well.
If you’re still having a problem paste us your nginx config and we can help go through it.
Thanks
Is there a different HOWTO for PHP7 FPM?
I found this helpful: https://www.tqhosting.com/kb/464/How-to-install-PHP-70-PHP-FPM-on-Ubuntu-1604-LTS-Xenial-Xerus.html
Here is my /etc/nginx/sites-available/default code:
http://d.pr/n/KgJt
You have a small typo near the end :
location ~ /.ht { deny all; } }
It should be:
location ~ /.ht/ { deny all; } }
However, this wouldnt be the cause for the issues you were having. I did test the URL via the IP for both a non-existent file, received the 404, and a non-existent file ending in .php and got good 404 errors for both.
Visiting the IP directly I did get the phpinfo() page, I’m assuming you made an index.php?
If that’s the case I don’t really see what issue you are having unless you are uploading php files and they aren’t displaying or if you are uploading static content and having an issue.
What URL are you hitting that you should see something and you dont? And can you show me the file listing in: /srv/www/test/
Thanks.
raiyu, thanks for the help, I solved the problem today, that’s why you got the 404 working.
Here is my modified /etc/nginx/sites-available/default code. Hope it helps in case that someone have the same issue:
http://d.pr/n/IRuL
Hello. Your tutorial is good. I want to change the current document root directory to “home/user101/box/devs” How can I do that? I’m new to Nginx. Thanks and more power!
Inside the server { } directive there is a root directive that which specifies where to serve files from:
server { root /home/user101/box/devs; }
i try everyting this is fun but really boring;
500 Internal Server Error
nginx/1.1.19 all the time.
but still better than regular hosting. i am going old school LAMP :D
Check your error log and paste why its returning a 500 error for you.
For security reasons any error will return 500 publicly so as not to distribute any sensitive error messages to the public internet.
It could be something as simple that the PHP script you are executing is being executed but is simply failing because of a code issue.
I’m getting a 502 gateway error…
[error] 15479#0: 1 connect() failed (111: Connection refused) while connecting to upstream, client: ...*, server: 141.0.170.212, request: “GET /info.php HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”, host: “141.0.170.212”
Seems to me that the server is refusing connections to port 9000, but I’ve not made any changes to disallow this (nor any to allow it really).
Thanks.
I’ve not solved the issue directly, but I found that the issue could of been I was using Ubuntu 12.10 x64. I’m now using 12.4 x32 and it works perfectly.
Nice HowTo! Now, as a totally n00b to nginx, how do I configure it to redirect all WAN incoming traffic to a virtualserver while sending all LAN traffic to another virtual server? Thanks in advance, Martin
There are a number of ways to do this, the easiest way is to setup a separate domain / server_name / server block for the internal LAN.
Then for internal communication since you would be communicating on different IPs that would take care of it.
So the public communication would be over the public IP with the listen directive, while the local communication can be done by setting the listen directive to a private LAN IP. Since the LAN IP is not visible from the public internet any communication that occurs over it is automatically private.
And it doesn’t require any complex proxying rules.
I am having memory issue with ubantu 12.04 droplet. After installing nginx/php/mysql and web2py I have found that memory is is slowly used up and needed to reboot to free up. So discarded every thing and rebuild the droplet. Nothing is installed on it, still memory issues remains.
Here is the detail: https://docs.google.com/open?id=0B3z4rMfDQSHIcmpLZ1pqU1JVbjg
Depending on the process you are running memory isn’t always freed up, instead it is cached until another application needs to use it.
If you are consistently having issues I’d recommend you install swap space according to this tutorial: https://www.digitalocean.com/community/articles/how-to-add-swap-on-ubuntu-12-04
This should help in your situation and if you start using a lot of swap you may want to resize to a larger virtual server because you may just be running more applications than your virtual server can support.
After doing some experiment with ubantu, found that even in a new instance if you just run these : #sudo apt-get update #sudo apt-get -u upgrade the used memory will not be freed long after the execution. It is only freed after you do a reboot.
so I destroyed my ubantu instance and created a fedora instance:
Last login: Thu Dec 20 20:13:36 2012 from 180.234.111.171 [root@fedora01 ~]# free -m total used free shared buffers cached Mem: 497 428 68 0 33 359 -/+ buffers/cache: 35 461 Swap: 0 0 0 [root@fedora01 ~]# history 1 free -m 2 free -m 3 yum update 4 free -m 5 free 6 free -m 7 top 8 free -m 9 top 10 free -m 11 history [root@fedora01 ~]#
The above are all the commands that was run after the instance created. RAM is already used up and i guess wont be released until a reboot.
RAM should get freed up as different applications are started and start using memory since a lot of memory gets used as cache and will be automatically replaced.
Also if you add swap space: https://www.digitalocean.com/community/articles/how-to-add-swap-on-ubuntu-12-04
You can give your virtual server a buffer so if you do end up using more RAM than your system has you will see your swap space grow. Otherwise you should see that the cached memory is released and used up by other applications without increasing swap usage.
i try everyting this is fun but really boring;
500 Internal Server Error
nginx/1.1.19 all the time.
but still better than regular hosting. i am going old school LAMP :D
Check your error log and paste why its returning a 500 error for you.
For security reasons any error will return 500 publicly so as not to distribute any sensitive error messages to the public internet.
It could be something as simple that the PHP script you are executing is being executed but is simply failing because of a code issue.
I’m getting a 502 gateway error…
[error] 15479#0: 1 connect() failed (111: Connection refused) while connecting to upstream, client: ...*, server: 141.0.170.212, request: “GET /info.php HTTP/1.1”, upstream: “fastcgi://127.0.0.1:9000”, host: “141.0.170.212”
Seems to me that the server is refusing connections to port 9000, but I’ve not made any changes to disallow this (nor any to allow it really).
Thanks.
I’ve not solved the issue directly, but I found that the issue could of been I was using Ubuntu 12.10 x64. I’m now using 12.4 x32 and it works perfectly.
Nice HowTo! Now, as a totally n00b to nginx, how do I configure it to redirect all WAN incoming traffic to a virtualserver while sending all LAN traffic to another virtual server? Thanks in advance, Martin
There are a number of ways to do this, the easiest way is to setup a separate domain / server_name / server block for the internal LAN.
Then for internal communication since you would be communicating on different IPs that would take care of it.
So the public communication would be over the public IP with the listen directive, while the local communication can be done by setting the listen directive to a private LAN IP. Since the LAN IP is not visible from the public internet any communication that occurs over it is automatically private.
And it doesn’t require any complex proxying rules.
I am having memory issue with ubantu 12.04 droplet. After installing nginx/php/mysql and web2py I have found that memory is is slowly used up and needed to reboot to free up. So discarded every thing and rebuild the droplet. Nothing is installed on it, still memory issues remains.
Here is the detail: https://docs.google.com/open?id=0B3z4rMfDQSHIcmpLZ1pqU1JVbjg
Depending on the process you are running memory isn’t always freed up, instead it is cached until another application needs to use it.
If you are consistently having issues I’d recommend you install swap space according to this tutorial: https://www.digitalocean.com/community/articles/how-to-add-swap-on-ubuntu-12-04
This should help in your situation and if you start using a lot of swap you may want to resize to a larger virtual server because you may just be running more applications than your virtual server can support.
After doing some experiment with ubantu, found that even in a new instance if you just run these : #sudo apt-get update #sudo apt-get -u upgrade the used memory will not be freed long after the execution. It is only freed after you do a reboot.
so I destroyed my ubantu instance and created a fedora instance:
Last login: Thu Dec 20 20:13:36 2012 from 180.234.111.171 [root@fedora01 ~]# free -m total used free shared buffers cached Mem: 497 428 68 0 33 359 -/+ buffers/cache: 35 461 Swap: 0 0 0 [root@fedora01 ~]# history 1 free -m 2 free -m 3 yum update 4 free -m 5 free 6 free -m 7 top 8 free -m 9 top 10 free -m 11 history [root@fedora01 ~]#
The above are all the commands that was run after the instance created. RAM is already used up and i guess wont be released until a reboot.
RAM should get freed up as different applications are started and start using memory since a lot of memory gets used as cache and will be automatically replaced.
Also if you add swap space: https://www.digitalocean.com/community/articles/how-to-add-swap-on-ubuntu-12-04
You can give your virtual server a buffer so if you do end up using more RAM than your system has you will see your swap space grow. Otherwise you should see that the cached memory is released and used up by other applications without increasing swap usage.