RickBacci
1/31/2011 - 7:43 PM

*AWESOME* nginx configuration for Ruby/Rack web applications

AWESOME nginx configuration for Ruby/Rack web applications

#
#   mmm  m     m  mmm    mmm    mmm   mmmmm   mmm  
#  "   # "m m m" #"  #  #   "  #" "#  # # #  #"  # 
#  m"""#  #m#m#  #""""   """m  #   #  # # #  #"""" 
#  "mm"#   # #   "#mm"  "mmm"  "#m#"  # # #  "#mm" 
# 
# nginx configuration For Ruby/Rack web applications
#
# Cooked up with style, care and a bit of *secret*
# nerdy spice. :-)
#
#  - vjt@openssl.it  Mon Jan 31 20:39:51 CET 2011
#
user nginx;
worker_processes 1;

error_log /var/log/nginx/error.log;
pid       /var/run/nginx.pid;

events {
    # If you're on Linux, you'd better use epoll
    use kqueue;
    worker_connections 256;
}

http {
    include         /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      /var/log/nginx/access.log main;

    sendfile        on;
    tcp_nopush      on;
    tcp_nodelay     on;

    # Where your Rails upstream is located. nginx works well
    # with mongrel/thin, works *better* with unicorn, that
    # can be configured to listen onto a UNIX socket as well,
    # bypassing the TCP/IP stack for incoming requests.
    #
    upstream rails {
      server 127.0.0.1:8080; # Unicorn default port is 8080
      #server unix:/var/run/nginx/rails.sock;
    }

    # HTTP server
    #
    server {
        listen      80;
        server_name example.com;

        # Let's say that your Rails app is in /var/www/example...
        set  $app /var/www/example;
        # ...thus nginx root is in /var/www/example/public.
        root $app/public;

        # Set a limit to POST data sent by clients. If you
        # plan to receive large file uploads, you must raise
        # up this value.
        client_max_body_size 8M;

        # Errors generated by Rails
        error_page 400     /400.html;
        error_page 422     /422.html;
        error_page 500 504 /500.html;

        # Errors generated *outside* Rails
        error_page 502     @502;
        error_page 503     @503;

        # If the public/system/maintenance.html file exists,
        # return a 503 error, that ...
        if (-f $document_root/system/maintenance.html) {
          return 503;
        }

        # ... will serve the very same file. This construct
        # is needed in order to stop the request before
        # handing it to Rails.
        location @503 {
          rewrite ^ /system/maintenance.html break;
        }

        # When a 502 error occurs - that is, Rails is not
        # running, serve the 502.html file
        location @502 {
          rewrite ^ /502.html break;
        }

        # Add client-side caching headers to static files
        #
        location ~ ^/(stylesheets|javascripts|images|system/avatars) {
            expires 720h;
        }

        # If you plan to serve files from your app, you'd
        # better read the send_file documentation and set
        # up the following X-Accel-Redirect block. This
        # configures the $app/tmp directory contents to be
        # served directly by nginx, without hogging up the
        # Rails backend.
        #
        #location /tmp {
        #  internal;
        #  root $app;
        #}

        # Hand over the request to Rails, setting headers
        # that will be interpreted by request.remote_ip,
        # request.ssl? and request.host
        #
        location / {
            proxy_set_header    X-Real-IP         $remote_addr;
            proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto http;
            proxy_set_header    Host              $http_host;
            proxy_redirect      off;

            # If the file exists as a static file serve it directly
            #
            if (-f $request_filename) {
                break;
            }

            # If you use Rails file caching, you should enable
            # the following block. But you'd better use memcached
            # anyway :-)
            #
            #if (-f $request_filename.html) {
            #    rewrite ^ $1.html break;
            #}

            # Oh yeah, hand over the request to Rails! Yay! :-D
            proxy_pass http://rails;
        }
    }

    # HTTPS Server
    #
    server {
        listen      443;
        server_name example.com;

        # These directives should point to your SSL certificate
        # and corresponding private key
        # 
        ssl on;
        ssl_certificate     /etc/nginx/server.crt;
        ssl_certificate_key /etc/nginx/server.key;

        # The rest of the configuration is the same as above,
        # but without comments :-)
        set  $app /var/www/example;
        root $app/public;

        client_max_body_size 8M;

        error_page 400     /400.html;
        error_page 422     /422.html;
        error_page 500 504 /500.html;

        error_page 502     @502;
        error_page 503     @503;

        if (-f $document_root/system/maintenance.html) {
          return 503;
        }

        location @503 {
          rewrite ^ /system/maintenance.html break;
        }

        location @502 {
          rewrite ^ /502.html break;
        }

        location ~ ^/(stylesheets|javascripts|images|system/avatars) {
            expires 720h;
        }

        # For X-Accel-Redirect
        #
        #location /tmp {
        #  internal;
        #  root $app;
        #}

        location / {
            proxy_set_header    X-Real-IP         $remote_addr;
            proxy_set_header    X-Forwarded-For   $proxy_add_x_forwarded_for;
            proxy_set_header    X-Forwarded-Proto https;
            proxy_set_header    Host              $http_host;
            proxy_redirect      off;

            if (-f $request_filename) {
                break;
            }

            #if (-f $request_filename.html) {
            #    rewrite ^ $1.html break;
            #}

            proxy_pass http://rails;
        }
    }
}
#
# vim: ft=nginx