Search code examples
ruby-on-railsruby-on-rails-3ruby-on-rails-3.1nginxunicorn

Error Messages Showing in Production - Ruby on Rails 3.1, Nginx, Unicorn


I have a Rails 3.1 app running in production using Nginx and Unicorn. And for some reason, my custom 404 and 500 html error pages are not showing. Instead I'm getting the actual error message ("Routing Error", for example).

In my production.rb file, I have config.consider_all_requests_local = false

And on the same server with a nearly identical configuration, I have a 'staging' site that works just fine. The only difference, as far as I can tell, is that the production one has SSL while the staging does not.

Here is the Nginx config for the production app:

upstream unicorn_myapp_prod {
  server unix:/tmp/unicorn.myapp_prod.sock fail_timeout=0;
}

server {
  listen 80;

  server_name myapp.com;

  root /home/deployer/apps/myapp_prod/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;
  location @unicorn {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn_myapp_prod;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}


server {
  listen 443 default;
  ssl on;
  ssl_certificate /home/deployer/apps/myapp_prod/shared/ssl_certs/myapp_prod.crt;
  ssl_certificate_key /home/deployer/apps/myapp_prod/shared/ssl_certs/myapp_prod.key;


  server_name myapp.com;

  root /home/deployer/apps/myapp_prod/current/public;

  location ^~ /assets/ {
    gzip_static on;
    expires max;
    add_header Cache-Control public;
  }

  try_files $uri/index.html $uri @unicorn;
  location @unicorn {
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://unicorn_myapp_prod;
  }

  error_page 500 502 503 504 /500.html;
  client_max_body_size 4G;
  keepalive_timeout 10;
}

Any ideas? Thanks!


Solution

  • The https listener's location @unicorn block is missing the X-Forwarded-For directive.

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    

    It's in your http listener, but not the https listener.

    Assuming that Rails' force_ssl is successfully redirecting all of the http requests and your only errors are happening on https requests, it seems that would explain it.

    Also, to be very clear, there is a well known problem in Rack/Rails3 with respect to routing errors, which you specifically mention.

    https://rails.lighthouseapp.com/projects/8994/tickets/4444-can-no-longer-rescue_from-actioncontrollerroutingerror