submit to stumbleupon.com
[adventures] [creations] [articles] [photo] [journal] [about me]
opinions and images by m. werneburg since 1998

configuring nginx on joyent

by m. werneburg, 2010.07.31

This is our nginx configuration file in all of its glory. I've annotated it for the purpose of sharing what I've learned with the world.

intent

Our goals in using nginx as a front-end to our rails-based website were these: + to improve "user experience" (have quicker responses) + to improve security for the users and our website's software + to improve system resource allocation

To accomplish this, we deployed nginx as a lightweight web server to act as a proxy for the application server. Nginx handles all web requests, and passes on anything that has to be handled by the application server. Anything else it handles itself. These "other" requests are usually for "static" content (that's unchanging stuff like images and javascript files), which it serves directly. Bogus requests are passed on to a search engine URL that turns such requests into searches on our site.

The security and performance issues can't be overstated. Our website was partially removed from active service by someone (script kiddie) because I was still passing on too many requests to the application server. While that attempted intrusion attack didn't work, it certainly brought our application server to its knees. Part of the configuration you see below comes from an exhaustive description here. The GZIP configuration stuff I found here.

nginx.conf

In this file, SSLDIRECTORY and HOMEDIRECTORY are stand-ins for the real directories.

user www www;
worker_processes 1;
pid /var/spool/nginx/nginx.pid;

events {
    worker_connections 256; # mod mw was 1024
    user eventport;
    }

http {
    include /opt/local/etc/nginx/mime.types;
    default_type application/octet-stream;
    log_format main '$remote_addr—$remote_user [$time_local] $request '
        '"$status" $body_bytes_sent "$http_referer" '
        '"$http_user_agent" "$http_x_forwarded_for"';
    access_log /HOMEDIRECTORY/web/logs/nginx.access.log main;
    error_log  /HOMEDIRECTORY/web/logs/nginx.error.log;

    sendfile          on; # quicker file delivery
    tcp_nopush        on;
    keepalive_timeout 20; # was 60
    server_tokens     off;# don't talk about being nginx

    # fine-tuning GZIP behaviour
    gzip on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types      text/plain text/css application/x-javascript
text/xml application/xml application/xml+rss text/javascript;

    #
    # Application server addresses
    # + add more entries if necessary
    upstream caritas_appserver {
        server unix:/tmp/thin.caritas.0.sock;
        }

    #
    # main webserver for caritas.co.jp
    server {
        # basic configuration
        listen 80;
        server_name caritas.co.jp www.caritas.co.jp;
        charset utf-8;
        root /HOMEDIRECTORY/web/public;
        index index.html;

        # security-specific stuff
        # 
        # only accept requests to this website
if ($host !~ ^(caritas.co.jp|www.caritas.co.jp|blog.caritas.co.jp)$ ) {
            return 444;
            }

        # only accept requests of this kind
        if ($request_method !~ ^(GET|HEAD|POST)$ ) {
            return 444;
            }

        # bad user agents
        if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
            return 403;
            }

        # tuning for performance and security
        client_body_buffer_size     1k;
        client_header_buffer_size   1k;
        client_max_body_size        1k;
        large_client_header_buffers 2 1k;
        client_body_timeout         20;
        client_header_timeout       20;
        keepalive_timeout           5 5;
        send_timeout                20;

        # reject requests for things no one needs
        location ~ /.ht { # .htusers and .htaccess files
            deny all;
            }

        location ~ /.svn { # version management stuff
            deny all;
            }

        # handle image requests and other static content
        location ~* ^.+.(js|css|jpg|png)$ {
            access_log off;
            expires    30d;
            }

        #
        # redirects
        #
        # On every website, things tend to move
        location ~ /public/about* {
            rewrite "^/public/about/(.*)$" /about/$1 permanent;
            }

        location ~ /howto* {
rewrite ^/howto(.*)$ http://blog.caritas.co.jp/post/532829816 redirect;
            }

        #
        # how to handle special content
        #

        # user tracking software
        location ~ /mint* {
            rewrite ^/mint(.*)$ http://caritas.co.jp:8080/mint$1 redirect;
            }

        #
        # pass these on to the SSL server
        #
        # order a sample ring
        location ~ /store/sample.* {
            rewrite     ^/(.*)$ https://caritas.co.jp/$1 redirect;
            }

        # buying a ring
        location ~ /checkout.* {
            rewrite     ^/(.*)$ https://caritas.co.jp/$1 redirect;
            }

        #
        # Application server
        #
        # proxy configuration (for application server)
        proxy_set_header X-Real-IP  $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
        proxy_redirect off;

        # rails code, send to proxy
        location ~* ^/(store|public|about|advice) {
            proxy_pass http://caritas_appserver;
            break;
            }

        location / {

            # if you can't find a file but (file).html exists,
            # rename the requested object
            if (-f $request_filename/index.html) {
                rewrite (.*) $1/index.html break;
                }
            if (!-f $request_filename) {
                rewrite /(.*) http://www.google.co.jp/search?
hl=ja&q=site%3Acaritas.co.jp+$1 break;
                }
        
            }
        }

    server {
        # SSL server configuration. Much the same as above.
        listen 443;
        server_name caritas.co.jp www.caritas.co.jp;
        charset utf-8;
        access_log /HOMEDIRECTORY/web/logs/nginx.access.log main;
        error_log /HOMEDIRECTORY/web/logs/nginx.error.log;
        root /HOMEDIRECTORY/web/public;
        index index.html;

if ($host !~ ^(caritas.co.jp|www.caritas.co.jp|blog.caritas.co.jp)$ ) {
            return 444;
            }

        if ($request_method !~ ^(GET|HEAD|POST)$ ) {
            return 444;
            }

        if ($http_user_agent ~* LWP::Simple|BBBike|wget) {
            return 403;
            }

        client_body_buffer_size     1k;
        client_header_buffer_size   1k;
        client_max_body_size    1k;
        large_client_header_buffers 2 1k;
        client_body_timeout     10;
        client_header_timeout       10;
        keepalive_timeout       5 5;
        send_timeout        10;

        location ~ /.ht {
            deny all;
            }

        location ~ /.svn {
            deny all;
            }
        
        location ~ /mint* {
            deny all;
            }


        location ~* ^.+.(js|css|jpg|png)$ {
            access_log off;
            expires    30d;
            }

#
# These requests should not be handled by the SSL server. They do
# not contain sensitive content and can be handled by the lighter
# non-SSL web server.

        location ~ /advice.* {
            rewrite     ^/(.*)$ http://caritas.co.jp/$1 redirect ;
            }
        location ~* /store/show.* {
            rewrite     ^/(.*)$ http://caritas.co.jp/$1 redirect ;
            }
        location ~ /public.* {
            rewrite     ^/(.*)$ http://caritas.co.jp/$1 redirect ;
            }
        location ~ /about.* {
            rewrite     ^/(.*)$ http://caritas.co.jp/$1 redirect ;
            }

#
# Application server content
#
# These URL's should be handled by the application server,
# which hides behind the nginx proxy server. Note that even
# though this is a SSL proxy server, you DO NOT use SSL
# to communicate with the application server.

        location ~ /store/sample.* {
            proxy_pass http://caritas_appserver;
            break;
            }

        location ~ /checkout.* {
            proxy_pass http://caritas_appserver;
            break;
            }

        proxy_set_header X-Real-IP  $remote_addr;
        proxy_set_header X-Forwarded-For https;

        ssl on;
        ssl_certificate /SSLDIRECTORY/openssl.pem;
        ssl_certificate_key /SSLDIRECTORY/openssl.pem;
        ssl_prefer_server_ciphers on;

        location / {
            if (-f $request_filename/index.html) {
                rewrite (.*) $1/index.html break;
                }
            if (!-f $request_filename) {
                return 404;
                break;
                }
            }
        }
    }

Tokyo photo book

streets without names
streets without names
photos from Tokyo's streets

photo of the day

semai means narrow and I"m looking at you

what's new

高品質のジュエリー

高品質のジュエリー、永遠の価値

tools

rand()m quote

Meetings are indispensable when you don't want to do anything.
-John Kenneth Galbraith

copyright

Creative Commons License
reader comments
have your say
name
email
website
comments