Sponsored Link

Unravel The Music is a small startup; by that I mean we have no money, no financing, and we are owned and operated by two people. Therefore it is important that we get the most out of our server in terms of performance and cost and we have to do this without having to spend hours worrying about the server when we could be improving our design or code.

First off, without good hardware it's not going to matter how well your server is setup because you will be constantly worrying about whether your server is even up or if the datacenter is having another monthly outage. For this problem we recommend Linode. I'm sure there are plenty of other great VPS hosts out there but we have had a lot of luck with Linode and highly recommend them.

This how-to is going to assume that you already have a standard LAMP stack running, if not, there are plenty of tutorials and examples on how to get a LAMP stack running.

We have chosen to go with a standard Apache 2 installation using libapache2_mod_php5 over using Nginx (pronounced ‘Engine X') with fastCGI. You may be thinking “that is preposterous, why not just use Nginx as your webserver and ditch Apache?” I hate fastCGI, I've never had very good luck with it and most importantly I know Apache. Also, when all Apache has to worry about is the dynamic content, in this case PHP, it is quite fast, and has a smaller memory footprint then normal Apache usage.

Using Nginx as a reverse proxy is great for a few reasons. Firstly it handles static content very well. It is able to handle the requests and serve static content much faster in our tests and this has cut our page load time in about half (using YSlow with a clear cache). The memory footprint of Nginx is very small so this extra speed increase is worth every megabyte, in this case .6 megabytes of our total ram on a 540 megabyte server. Secondly, it allows for quick and easy migration of your Apache services to another server. Through the config files you are able to specify an IP of your server and a port. If your apache server is taking a pounding it wouldn't be difficult to move it to another server and just change the proxy IP to your now remote server.

Setting up Nginx is fairly straight forward. I will be showing the commands for an Ubuntu 8.04 installation but they should work for previous versions and other distributions (with a little tweaking).

Install Nginx

sudo apt-get install nginx

the following is essentially the config file we use for /etc/nginx/nginx.conf and is pretty similar to the default config for the installation. The only major thing I changed was adding gzip compression. I have personally set the level to 5 although it is adjustable. The higher you set this value the more CPU intensive it becomes.

The only thing you may want to change is the buffer sizes. We had to increase our proxy_buffer_size and a few others, from the default, to allow for larger cookies that were choking Nginx. With that being said you may want to decrease the buffers a bit, just do some testing. If the buffers are not working for your content Nginx will throw a 50x error.

Finally, we will configure the various hosts. To save yourself some time, and possible a headache you should always keep your static assets in one folder, while subdividing them by type in containing folders. For example static->images, static->js, static->css. This will greatly simplify your Nginx installation and I've found your code.

Now we will edit (with your favorite CLI editor) /etc/nginx/sites-available/default.

Finally we need to make some quick changes to Apache and we'll finally have everything running. Edit the file /etc/apache2/ports.conf.

You'll want to change the listen line to 127.0.0.1:8080. This will prevent apache from receiving requests from outside, but you should be blocking port 8080 anyways! The port we've set is 8080 but whatever you set in the Nginx configs is what you should use.

NameVirtualHost *
Listen 127.0.0.1:8080

Lastly, if you don't want all your apache logs to show 127.0.0.1 for who is accessing your files or your application uses IP's to track sessions you need to install libapache2-mod-rpaf. It is painless just issue the command below.

sudo apt-get install libapache2-mod-rpaf

reload or restart both Apache2 and Nginx.

/etc/init.d/apache2 restart
/etc/init.d/nginx restart

To see if it is working open a page on your website, if you don't see any errors that is a good start. You can then check the logs of Apache and Nginx. Your Apache logs should only contain the php requests and your Nginx logs should contain all of your assets. Your Apache logs should also have HTTP 1.0 request when they go through the reverse proxy.

If you need any support just leave a comment and we'll try and help you.

15 thoughts on “Using Nginx as a Reverse Proxy to Get the Most Out of Your VPS.”

Thank you so much for writing up this tutorial. There is a ton of info out there on setting up Nginx with Apache, and having it so cleanly laid out is nice.

A couple of clarifying questions would be helpful before jumping into the fray:

1. I’m not seeing any declarations of the types of static files that Nginx would handle in your examples unless it is the “application/octet-stream” or the fact that you are gzipping the static files and that is where they are declared.

2. You mention it a wise choice to organize static files together in structures like

“/static-folder/static-file.img-type”

Is this “required” for Nginx or simply “better”? And either way, does this imply that if Nginx is to serve those files, they have to be located there versus where a CMS might place them (for instance, WordPress placing uploaded images into the wp-content/uploads/ directory)?

Here is the thing, the two are directly related which is why I said it is important to have a static folder.

location /static {
root /var/www/example.com/htdocs/;
expires max;
}

These few lines tell Nginx that everything in the static folder it should handle by finding in the /var/www/example.com/htdocs/ folder. So anything coming into such as /static/css/style.css will be handled by Nginx because it is missing the proxy_pass command for this folder. Where as example.com/index.php will be passed to Apache.

This really works out well because if you only wanted Nginx to server your user uploaded images you would just have the location /wp-content/uploads/ command and apache would be passed everything else. I would definitely recommend having Nginx handle your css and js as we’ve seen great performance increases using this technique.

Hi, I exactly followed your tutorials and thanks a lot for your effort.
All servers seem to work as intended however, when I check apache2 access log, I see all static files request logs.
Does it mean apache still handle the static files?
What should I do?

Hi, I’m trying to do a failover for load balancer. I have 2 load balancer, I want to make sure that if one load balancer is down, all my request will be to the other load balancer. This is to ensure that I have no single point of failure. Is it possible to use nginx for this? Thanks.