Nginx: the High-Performance Web Server and Reverse Proxy

Having performance issues with your Web server? Maybe the Russians can help.
Reverse Proxy and Load Balancer

In addition to being an extremely fast static Web server, Nginx also is a load balancer and reverse proxy. A load balancer is a device used to spread work out across multiple servers or processes, and a reverse proxy is a server that transparently hands off requests to another server. Among other things, this allows Nginx to handle requests for static content and to load-balance requests for dynamic content across many different back-end servers or processes.

For this example, let's create a very simple Python Web server to serve up some dynamic content. Don't worry if you are not familiar with Python; we're just using it to display a Web page that indicates on which port the server is running. Save the following to a file called /tmp/

import sys,BaseHTTPServer as B
class Handler(B.BaseHTTPRequestHandler):
  def do_GET(self):
    self.wfile.write("Served from port %s" % port)
  def log_message(self, *args):
if __name__ == '__main__':
  host,port = sys.argv[1:3]
  server = B.HTTPServer((host,int(port)), Handler)

Now we can start two of these local servers, each on a different port:

# python /tmp/ 8001 &
# python /tmp/ 8002 &

If you open in your browser, you should see “Served from port 8001”, and if you open, you should see “Served from port 8002”.

Now, create a new configuration file called /etc/nginx/sites-available/proxy with the following contents:

upstream python_servers {
server {
  server_name  proxy;
  access_log  /var/log/nginx/proxy.access.log;
  error_log /var/log/nginx/proxy.error.log;
  location / {
    proxy_pass http://python_servers;

Enable the site and restart Nginx:

# cd /etc/nginx/sites-enabled
# ln -s ../sites-available/proxy .
# /etc/init.d/nginx restart

If you open in your browser, you should see a page with either “Served from port 8001” or “Served from port 8002”, and it should alternate each time you refresh the page.

Let's go over some of these new settings. The upstream block defines a name for a group of back-end servers. In our case, we defined a group named python_servers, which contains the two local Python servers we started on port 8001 and 8002. We then configured Nginx to hand off all requests to our back-end servers with the line proxy_pass http://python_servers;. Nginx automatically load-balances the requests to each Python server in a round-robin manner. You also can set weights for each back end, so you can direct more or fewer requests to specific servers.

Nginx handles back-end failures automatically and will stop sending requests to a failed back-end server until it starts responding again. To demonstrate this, we can kill off the Python process that's running on port 8001. Use the jobs command to find the job number for the Python process running on port 8001, and use kill %<job number> to kill the process:

# jobs
# kill %1

Open in your browser and keep refreshing the page, you should see only the “Served from port 8002” page. Nginx detected that the back-end server from port 8001 was not responding, so it stopped sending requests to that server. Now, restart the Python process for port 8001:

# python /tmp/ 8001 &

Keep refreshing the page and you should see your browser start alternating between “Served from port 8001” and “Served from port 8002” again. Nginx detected that the port 8001 back end was responding and began sending requests to it.


Whether you are looking to get the most out of your VPS or are attempting to scale one of the largest Web sites in the world, Nginx may be the best tool for the job. It's fast, stable and easy to use. Thanks to Igor Sysoev for creating this excellent piece of software.

Will Reese has worked with Linux for the past ten years, primarily scaling Web applications running on Apache, Python and PostgreSQL. He enjoys beating Cory Wright at foosball and Wii Tennis.



Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

Centos SETUP

M.T.'s picture

I wrote a small article for Redhat based OS. Here is the article: NGINX, PHP-CGI, SPAWN-FCI, FTP, VHOSTS, MYSQL | centos-fedora-redhat


1001 Fonts's picture

This helped me set up a reverse proxy. All I need to figure out now is how to use the caching ability of the nginx proxy.


Anonymous's picture

Thanks to Igor Sysoev for creating this excellent piece of software and thanks to you Will for this excellent piece of article! :-)

Hands down

mBma's picture

This is probably the best tutorial i've read ever!


Anonymous's picture

apt-get rocks

Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Upcoming Webinar
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
11am CDT, April 29th
Moderated by Linux Journal Contributor Mike Diehl

Sign up now

Sponsored by Skybot