Nginx by examples: reverse proxy

Nginx is primarily designed as a reverse proxy and can add a lot of value if placed in front of your applications:

Let’s see how we can setup a basic Java API webapp behind Nginx

server {

    # custom virtual host root folder
    root /var/www/;

    # index file (when a folder URI is matched)
    index index.html;

    # server name (for virtual host resolution)

    # custom access and error log
    access_log /var/www/;
    error_log /var/www/ error;

    # the default catchall block
    location / {
        # this will return a 403 http error code
        deny all;

    # we server some static welcome page if present on a / request
    location =/ {
        try_files /index.html =404;

    # our apis are under /api
    location /api {

        # we tunnel through to the java web app living on localhost

        # we tweak the send and receive timeout (especially if our backend can be a bit slow)
        proxy_send_timeout 600;
        proxy_read_timeout 600;

Pretty straightforward.

If we have multiple apps hosted on the same server we can simply add another location block as follows

# our documentation is dynamically generated and served by another web app
location /docs {

    # we intercept all 302 redirects to prefix all URIs with /docs/
        # after the response has been generated by the downstream server
    proxy_redirect / /docs/;

The use of proxy_redirect is quite handy when the proxied app has no knowledge of the URL its content is actually served from.

Proxying 3rd party servers #

If we need to proxy content from another server (from Amazon S3 for example) the configuration has to be extended a bit

location /docs {

    # we force http/1.1 to take advantage of keep alive sockets
    proxy_http_version 1.1;

    # we replace the host header (for correct virtual host resolution)
    proxy_set_header Host $s3_bucket;

    # we hide some S3 specific headers
    proxy_hide_header x-amz-id-2;
    proxy_hide_header x-amz-request-id;
    proxy_hide_header Set-Cookie;

        # we can discard any cookie set by Amazon
    proxy_ignore_headers "Set-Cookie";

    # we serve the nginx error pages (as opposed to the S3 ones)
    proxy_intercept_errors on;

    # We force the method to GET in the downstream server to prevent
        # POST/PUT/DELETE requests against S3 that would result in errors
    proxy_method GET;

    # we setup a DNS resolver using Google open DNS servers
    resolver_timeout 10s;

    # we finally tunnel the request

Notes #


Now read this

Evolving CRUD (part 1)

Serving content at scale limiting complexity Scalability is a simple concept that proves difficult to achieve without introducing complexity Create Read Update Delete # CRUD stands for Create Read Update Delete and identifies all the... Continue →