# A commented nginx configuration file for Ruby on Rails # # Author: Tommaso Pavese # tommaso@pavese.me # www.wonderingmachine.com # # License: http://www.wtfpl.net/ # # # Tested with: # Ubuntu 12.04 # nginx 1.4.1 - 1.4.4 # Rails 3.2 - 4.0 # Unicorn, Thin and Puma # # # Docs: # http://nginx.org/en/docs/ # # Configuration measurement units: # http://nginx.org/en/docs/syntax.html # # Each module can define its variables, the core ones: # http://nginx.org/en/docs/http/ngx_http_core_module.html#variables # # # As reference, the official example for nginx + unicorn: # https://github.com/defunkt/unicorn/blob/master/examples/nginx.conf # # # In order to bind to port 80, the master process must be executed as root: # $ sudo /usr/sbin/nginx -c /etc/nginx/nginx.conf # # How to execute the worker processes user user_name group_name; # A single worker is enough for load balancing and reverse proxing. # However: # Disk I/O can block an nginx worker (depends on disk read performance). # If the server is serving a lot of static files (e.g. assets) it is # a good idea to increase the number of worker processes. worker_processes 1; # The limit on the maximum number of open files for worker processes. # "open files" is intended as UNIX open file descriptors. # This overrides the limit set by the OS for the user the workers run as. # Run `ulimit -a` in a shell to see the current limit. worker_rlimit_nofile 2048; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; # -------------------------------------------------------- events { worker_connections 1024; # increase if you have lots of clients accept_mutex off; # "on" if nginx worker_processes > 1 use epoll; # best for Linux 2.6+ ("kqueue" for FreeBSD, OSX) } # -------------------------------------------------------- http { # MIME types include mime.types; # the path is relative to this conf file, # in this case /etc/nginx/mime.types # fallback MIME type if the client doesn't specify it. default_type application/octet-stream; # log access_log /var/log/nginx/access.log combined; # TCP settings tcp_nopush on; tcp_nodelay off; # use unix sendfile() sendfile on; # gzip compression gzip on; gzip_http_version 1.0; gzip_proxied any; gzip_vary on; gzip_min_length 500; gzip_disable "MSIE [1-6]\."; gzip_types text/plain text/xml text/css text/comma-separated-values text/javascript application/x-javascript application/atom+xml; # text/html is included by default # According to the HTTP standard, headers with underscores are perfectly valid. # However, nginx defaults to dropping headers containing underscores, as they # might introduce ambiguities when mapping headers to CGI variables. # # Since this is not a problem with Ruby on Rails, we can safely enable them. underscores_in_headers on; # -------------------------------------------------------- # It's possible to organize the server configuration in different files. # # Typically, these site-specific files contain at least: # - a server{} block # - an upstream{} block # # The convention is to store configuration files in: # /etc/nginx/sites-availbale/ # # and then symlink them into: # /etc/nginx/sites-enabled/ # # with: # $ ln -s /etc/nginx/sites-availbale/example.com.conf /etc/nginx/sites-enabled/example.com.conf # # After that, send a HUP signal to the nginx master to reload the configuration on the fly: # $ sudo kill -HUP `cat /var/run/nginx.pid` # # include /etc/nginx/sites-enabled/*; # -------------------------------------------------------- # upstream destinations # # http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream # # fail_timeout=0 means we always retry an upstream even if it failed # to return a good HTTP response. # This happens when the Unicorn master nukes a single worker for timing out. # # Sockets can be opened at any location where the user has writing access, # even inside the rails_root/tmp/sockets directory # # We can also use IP addresses and domain names, and mix them together. # # If more than one destination server is specified, the requests # are distributed using a weighted round-robin balancing method. # # Important: # Unicorn workers can all listen on the same Unix socket (or TCP port) # at the same time. # However, this might not be true for other servers. # A cluster of Thins, for example, will require a Unix socket per process. # Look at the second upstream block for an example. # This works well with Unicorn (yes, even with several workers) upstream rails_app_one { server unix:/tmp/rails_app_one.sock fail_timeout=0; } # This will work with a cluster of 3 Thin servers upstream rails_app_two { server unix:/tmp/rails_app_two.0.sock fail_timeout=0; server unix:/tmp/rails_app_two.1.sock fail_timeout=0; server unix:/tmp/rails_app_two.2.sock fail_timeout=0; } # This is weird, but it would still work. upstream rails_app_three { server unix:/tmp/rails_app_three.sock fail_timeout=0; server 192.168.0.7:8080 fail_timeout=0; server 127.0.0.1:3000 weight=3 fail_timeout=0; server backendworker.example.com weight=5 fail_timeout=0; } # -------------------------------------------------------- # servers # This server listens to port 80 and 443, and is configured to accept # both HTTP and HTTPS traffic on the same domain. # The Rails app can then decide to enforce HTTPS on the whole application # or only on specific controllers. # server { # Only one server can use the 'default_server' and 'deferred' options. listen 80 default_server deferred; # http://nginx.org/en/docs/http/ngx_http_core_module.html#server_name # # Also accepts lists of names, wildcard characters and regular expressions. # Make sure that they all match the SSL/TSL certificate, if using one. # See the last server block for more examples. server_name www.example.com; # HTTPS # http://nginx.org/en/docs/http/configuring_https_servers.html # # If the key has a passphrase, nginx will require it each time it will # boot or restart (making automatic management impossible). listen 443 ssl; ssl_certificate /etc/nginx/sslfiles/example_com_chained.crt; ssl_certificate_key /etc/nginx/sslfiles/example_com_ssl_nopf.key; ssl_session_cache shared:example_ssl_cache:1m; ssl_session_timeout 5m; client_max_body_size 4G; # default 1M keepalive_timeout 20s; # default 75s root /var/www/example/current/public; # http://nginx.org/en/docs/http/ngx_http_core_module.html#try_files # # Tries URIs in sequence until one is found. # First we try to serve static files directly from nginx. # The rails application is the last alternative. # # See comment block at the end of the file for detailed examples. # # /maintenance.html can be symlinked into public/ to stop requests # before they reach the rails app (e.g. while updating the DB). # When it does not exist (normally), it's quickly skipped. # try_files /maintenance.html $uri $uri/index.html $uri.html @rails_app; # The location directory allows very creative configurations. # http://nginx.org/en/docs/http/ngx_http_core_module.html#location # # This is just a named location to be used in try_files. location @rails_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # the client IP proxy_set_header X-Real-IP $remote_addr; # the client IP (again) proxy_set_header X-Forwarded-Proto $scheme; # pass scheme (for HTTPS) proxy_set_header Host $http_host; # the full host, for redirects within Rails proxy_redirect off; # disable nginx redirect-rewrite logic proxy_pass http://rails_app_one; # http is to be used even for https traffic } # Customize what html file should be served for different errors. error_page 500 502 503 504 /500.html; # This location block isn't strictly required, as '/500.html' # can also be served by 'try_files $uri', above. Still, this # location is more precise (thus has higher priority) and can # be used to further customize the error response. # # location = /500.html { } } # A redirect from the naked domain to www # # This listens to port 80, thus it can't handle HTTPS traffic. # (therefore, using $scheme instead of http is a bit useless) # # If the certificate is also compatible with the naked domain, # then this server block can be improved by replicating here # the SSL configuration of the main server. server { listen 80; server_name example.com; return 301 $scheme://www.example.com$request_uri; } # ---------------------------- # This server block features an efficient configuration # to serve the pre-gzipped version of the static assets server { listen 80; server_name .winter.is.coming.com www.winteriscoming.com *.winteriscoming.net; client_max_body_size 4G; keepalive_timeout 10s; root /var/www/winteriscoming/current/public; try_files $uri $uri/index.html $uri.html @rails_app; error_page 500 502 503 504 /500.html; location @rails_app { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://rails_app_two; } # Location block for the assets. # See: http://guides.rubyonrails.org/asset_pipeline.html#gzip-compression # # '^~ /assets/' is a 'prefix string', not a regex. # '^~' will prevent further location searching after this location is matched. # # 'root' is inherited from the parent block. With the default Rails directory # structure it should point to 'app_root/public'. # location ^~ /assets/ { # To serve the pre-gzipped version of the files, if available. # The non-compressed versions MUST be available too, or a 404 will be returned. # The general gzip directives in the 'http' block are still applied. gzip_static on; # Since Rails automatically appends digest fingerprints to asset file names, # we don't need to worry about expiring them. expires max; add_header Cache-Control public; # Or: # expires 12h; # add_header Cache-Control "public, must-revalidate"; # The 'try_files' directive is NOT inherited from the parent block. try_files $uri =404; # We could also use a less strict directive that falls back to the Rails app # if a requested asset cannot be found. In this case, the cache headers here # configured will be ignored and Rails will set them automatically. # try_files $uri @rails_app; # Normally the Rails app takes care of serving the static file 'public/404.html' # when a 404 occours. Here, however, it will be handled by nginx. error_page 404 /404.html; } } } # A note on $uri and the try_files directive: # # try_files /maintenance.html $uri $uri/index.html $uri.html @rails_app; # # # /maintenance.html # if this file exists (likely a symlink), the app is probably not # available (updating the DB?). We serve it directly. # # $uri # it could be an asset. # e.g. assets/application.css # # $uri/index.html # it could be a directory in the file system. In that # case we look for an index.html file. # # $uri.html # it could be an actual html file. # e.g. 500.html # # @rails_app # finally, if all other tests fail, we pass the request to the app #