1

I have an index.html in public/ that should be loading by default but instead I get a 404 error when I try to access http://example.com/

The page you were looking for doesn't exist.

You may have mistyped the address or the page may have moved.

This has something to do with nginx and unicorn which I am using to power Rails 3

When take unicorn out of the nginx configuration file, the problem goes away and index.html loads just fine.

Here is my nginx configuration file:

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

server {
    server_name example.com;
    root /www/example.com/current/public;
    index index.html;

    keepalive_timeout 5;

    location / {
        try_files $uri @unicorn;
    }

    location @unicorn {
        proxy_pass http://unicorn;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
        proxy_redirect off;
    }
}

My config/routes.rb is pretty much empty:

Advertise::Application.routes.draw do |map|
  resources :users
end

The index.html file is located in public/index.html and it loads fine if I request it directly: http://example.com/index.html

To reiterate, when I remove all references to unicorn from the nginx conf, index.html loads without any problems, I have a hard time understanding why this occurs because nginx should be trying to load that file on its own by default.

--

Here is the error stack from production.log:

Started GET "/" for 68.107.80.21 at 2010-08-08 12:06:29 -0700
  Processing by HomeController#index as HTML
Completed   in 1ms

ActionView::MissingTemplate (Missing template home/index with {:handlers=>[:erb, :rjs, :builder, :rhtml, :rxml, :haml], :formats=>[:html], :locale=>[:en, :en]} in view paths
"/www/example.com/releases/20100808170224/app/views", 
"/www/example.com/releases/20100808170224/vendor/plugins/paperclip/app/views", 
"/www/example.com/releases/20100808170224/vendor/plugins/haml/app/views"):
/usr/local/rvm/gems/ruby-1.9.2-rc2/gems/actionpack-3.0.0.beta4/lib/action_view/paths.rb:14:in `find'
  /usr/local/rvm/gems/ruby-1.9.2-rc2/gems/actionpack-3.0.0.beta4/lib/action_view/lookup_context.rb:79:in `find'
  /usr/local/rvm/gems/ruby-1.9.2-rc2/gems/actionpack-3.0.0.beta4/lib/action_view/base.rb:186:in `find_template'
  /usr/local/rvm/gems/ruby-1.9.2-rc2/gems/actionpack-3.0.0.beta4/lib/action_view/render/rendering.rb:45:in `_determine_template'
  /usr/local/rvm/gems/ruby-1.9.2-rc2/gems/actionpack-3.0.0.beta4/lib/action_view/render/rendering.rb:23:in `render'
  /usr/local/rvm/gems/ruby-1.9.2-rc2/gems/haml-3.0.15/lib/haml/helpers/action_view_mods.rb:13:in `render_with_haml'
  etc...

--

nginx error log for this virtualhost comes up empty:

2010/08/08 12:40:22 [info] 3118#0: *1 client 68.107.80.21 closed keepalive connection

My guess is unicorn is intercepting the request to index.html before nginx gets to process it.

Miko
  • 1,759
  • 4
  • 22
  • 28
  • Please add "error_log /path/to/error.log info;" to config and provide any info related to the 404. – Martin Fjordvald Aug 08 '10 at 19:23
  • Looks like the request never reaches nginx in the first place because nginx's error log shows nothing except that it closed a keepalive connection. – Miko Aug 08 '10 at 19:43

3 Answers3

1

Rails 3 does not serve static assets by default. You have to configure your web server to serve up the public server or add

config.serve_static_assets = true

to your production environment http://docs.heroku.com/rails3

Julien
  • 126
  • 1
1

This seems to work. I had to edit the nginx config file: /etc/nginx/servers/appname.conf

location / {
  ...stuff...

  # check for index.html for directory index
  # if its there on the filesystem then rewite 
  # the url to add /index.html to the end of it
  # and then break to send it to the next config rules.
  if (-f $request_filename/index.html) {
    rewrite (.*) $1/index.html break;
  }

  ...other stuff..

}

Using config.serve_static_assets = true only came up with about half the requests per second as I get after adding this and having config.serve_static_assets = false

ddd
  • 11
  • 1
1

The problem is here:

    try_files $uri @unicorn;

This should read:

    try_files $uri $uri/ @unicorn;

Which also eliminates the need to use an evil if, and doesn't require you to have Rails serve static files (which is slow).

Michael Hampton
  • 244,070
  • 43
  • 506
  • 972