development and systems administration
The web has continued to grow at ever increasing speed, along with that growth comes increased demands on server response time. It’s becoming quite clear that, although Apache has been a long-standing pillar in the world of the web, it no longer makes sense as an ‘across the board’ solution to serving web pages.
This may seem completely obvious to some groups of people, while to others - Apache is still that familiar face they don’t want to part with. Then there’s the common case of having an existing infrastructure built around Apache that is, more or less, operating acceptably. You can’t justify ripping out pieces just because there exists a (possibly) better solution. In these cases small, cautious, steps are the only real way to go about changing things.
For a majority of people transition is inevitable, however - to ease the possible transition, I suggest giving Nginx a try in a very non-intrusive way: as part of your existing server setup, and not removing Apache altogether (just yet). Here are 5 reasons why you should add Nginx to your LAMP stack today.
OK, so this is definitely not a major reason. After all, you shouldn’t install something just because it’s easy. However I do think a lot of people tend to avoid new things out of fear they will have to spend hours learning new concepts and configuration oddities. This is most definitely not the case with Nginx.
I figured it would be best to mention this reason first, so that I can take you through the setup and lay the foundation.
On an Ubuntu system (12.04), setup took only a few minutes. First, install Nginx:
sudo apt-get install nginx
For the purposes of this article, I’m going to assume you are using Nginx version 1.1.x which is what is packaged for Ubuntu 12.04, otherwise some configuration options we add may not work (like proxy_http_version).
The default configuration is fine as it is, though you will want to add some proxy directives to /etc/nginx/nginx.conf at the end of (but still inside) the http { } section
http {
... default config skipped ...
# proxy settings
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_max_temp_file_size 0;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_temp_file_write_size 256k;
}
Now, you’ll want to setup your specific site config. On Ubuntu the setup is very similar to Apache. You have your /etc/nginx/sites-available/default config file. Here’s what mine looks like:
server {
listen 80;
server_name <domain_name>
location / {;
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
client_max_body_size 10m;
client_body_buffer_size 128k;
}
}
Remember, Nginx is going to act like a proxy. It will accept all incoming requests, and forward them to where they need to go. In this config we specify server_name as our front-facing domain name, listening on port 80. Then, for the location / directive, we specify the host & port that Apache will be listening on (I suggest localhost, port 8080).
Finally we need to tell Apache to stop listening on port 80, and instead to listen on port 8080. We do that with an easy change to the /etc/apache/ports.conf
NameVirtualHost *:8080
Listen 127.0.0.1:8080
I’m assuming here, you have NameVirtualHost setup. If so, make sure to also modify your site config and change the port number there as well, in /etc/apache/sites-available/default
<VirtualHost *:8080>
You’re done! Wasn’t that easy? Now just restart Apache and Nginx:
sudo /etc/init.d/apache restart
sudo /etc/init.d/nginx start
At this point, when you visit
The first tweak you can make to boost performance right away, is to set up Nginx to serve all static files for you. This takes load off Apache, as Nginx serves up static files much faster.
It’s extremely easy to setup, just add the following directive to your /etc/nginx/sites-available/default config file:
# serve static files location /res { root /var/www; expires 30d; }
I keep all my static files in the /res directory off my webroot, but you if keep static files in several different directories, it’s easy to add multiple locations at once. For example:
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
That directive will match any of those directories and serve their contents directly, instead of passing the request along to Apache.
Don’t forget to restart Nginx for the changes to take effect!
$ /etc/init.d/nginx restart
Nginx is very light weight and efficient. When put to the test against Apache it repeatedly outperforms, especially when it comes to handling concurrent connections.
This means that you are helping to increase the performance of Apache, as it won’t have to handle so many concurrent connections to serve up static content like images, css and js files.
This gives you immediate savings in resources for your server, even though you’ve actually added another layer to your stack.

graph from http://blog.zhuzhaoyuan.com/2012/02/apache-24-faster-than-nginx/
Nginx is a perfect choice for implementing things like long-polling or WebSockets. Having this proxy in place allows you to experiment with, and implement new ways to get your content to the front-end. With Nginx proxying to an asyncrhronous Python+Tornado app, you can slowly start to build stand-alone additions to your existing web application.
For example, I’ve begun implementing WebSockets for an existing large-scale LAMP application. It would be impossible to do this with Apache + the existing PHP code (which is huge). However with Nginx proxying for me, it’s dead simple to start slowly improving things with a simple Python+Tornado WebSocket app to push new events to the front-end using JSON. All I need to do is add a simple directive to my /etc/nginx/sites-available/default site conf.
location /notify {
proxy_pass http://127.0.0.1:8000;
proxy_redirect off;
}
Once I fire up my tornado service (which should be listening on port 8000), any requests to
Let’s say you outgrow your VPC a year down the road. Already having Nginx in place will make things a lot easier on you.
You can define groups of servers in your nginx.conf, all of which provide the same content. Then specify that group to proxy to. So, for example, you could set up another webserver with the LAMP stack, and add it to your list of servers in the nginx.conf. Now Nginx will load balance between your listed servers, the existing one and the new one.
In this way, you can easily start to offload services until all you have left on your original server is Nginx proxying requests through to your new farm of webservers.

image from http://scalr.net/blog/feature/2-1-feature-highlight-scale-from-one-to-many-servers/
I’ve always been a huge fan of Apache, but over time I’ve found myself in more varied development environments, and surprisingly I think the first performance hiccup is often not the database, or the code, but usually Apache (I have no proof to back up this claim:). This is because Apache tries to solve too many problems with one tool, and 90% of the problems it tries to address only apply to 10% of the scenarios.
The reason Nginx and Lighttpd are seeing increased usage, is because they address a few things really really well. These few things are usually all we need for a website.
What I’ve found really helps with this transitional approach, is that you can begin to test out your existing web application on Nginx, test the waters and see if everything works correctly. If so, you can eventually phase out Apache altogether (if that’s what you decide is appropriate). Alternatively, you can just leave Apache there, because the benefits of having Nginx in the stack still completely outweigh the downside of adding one more piece to the puzzle.