Im using Rails, Passenger (both are 3.0.5) and Nginx on my production server. As I heard, Rails should show public/404.html
or public/500.html
instead of development errors like ActiveRecord::RecordNotFound
or Unknown action
but that doesn't happen. I've tried to delete config.ru file and set rack_env or rails_env in nginx.conf but nothing helped.
Here is my nginx.conf:
worker_processes 1;
events {
worker_connections 1024;
}
http {
passenger_root /home/makk/.rvm/gems/ruby-1.9.2-p0/gems/passenger-3.0.5;
passenger_ruby /home/makk/.rvm/bin/passenger_ruby;
#passenger_ruby /home/makk/.rvm/wrappers/ruby-1.9.2-p0/ruby;
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
root /home/makk/projects/1server/deploy/current/public;
index index.html index.htm;
passenger_enabled on;
rack_env production;
recursive_error_pages on;
if (-f /home/makk/projects/1server/maintenance.html) {
return 503;
}
error_page 404 /404.html;
error_page 500 502 504 /500.html;
error_page 503 @503;
}
location @503 {
error_page 405 = /maintenance.html;
# Serve static assets if found.
if (-f $request_filename) {
break;
}
rewrite ^(.*)$ /maintenance.html break;
}
location ~ ^(\/phpmyadmin\/)(.*)$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_split_path_info ^(\/phpmyadmin\/)(.*)$;
fastcgi_param SCRIPT_FILENAME /usr/share/phpmyadmin/$fastcgi_path_info;
include fastcgi_params;
}
}
}
It seems that this question duplicates this one but there are no working suggestions.
UPD: I have both development and production apps on same PC. In production Rails ignores config.consider_all_requests_local = false
(in /config/environments/production.rb) due to local_request?
method. So one of possible solutions is listed below (taken from here):
# config/initializers/local_request_override.rb
module CustomRescue
def local_request?
return false if Rails.env.production? || Rails.env.staging?
super
end
end
ActionController::Base.class_eval do
include CustomRescue
end
Or for Rails 3:
class ActionDispatch::Request
def local?
false
end
end
To get this working in Rails 3 you'll have to do the following:
First, create your 404 and 500 error pages. I put mine in app/views/errors/404.html.erb
and app/views/errors/500.html.erb
.
Second, add the following to application_controller.rb:
unless Rails.application.config.consider_all_requests_local
rescue_from Exception, :with => :render_error
rescue_from ActiveRecord::RecordNotFound, :with => :render_not_found
rescue_from AbstractController::ActionNotFound, :with => :render_not_found
rescue_from ActionController::RoutingError, :with => :render_not_found
rescue_from ActionController::UnknownController, :with => :render_not_found
rescue_from ActionController::UnknownAction, :with => :render_not_found
end
def render_error exception
Rails.logger.error(exception)
render :template => "/errors/500.haml", :status => 500
end
def render_not_found exception
Rails.logger.error(exception)
render :template => "/errors/404.haml", :status => 404
end
Finally, make your production.rb not consider all requests local:
config.consider_all_requests_local = false
P.S: Keep in mind that when a complete routing error happens - i.e when there is absolutely no route match, not just an ActiveRecord NotFound error, the public/404.html will get displayed, so it's good to have that in place. I usually just re-direct it to my errors_controller, which ensures that any 404 errors not caught by the latter mentioned exceptions are still properly redirected to ErrorsController.
<script type="text/javascript">
<!--
window.location = "<%= request.host_with_port %>/errors/404"
//-->
</script>