title: Rails 3.2.2 getting a 404 on stylesheets and js assets after deployment with capistrano
body: <p>after pulling my hair out with this one, I'm afraid I'm going to have to turn the knowledge of those much wiser.....again!</p>
  
  <p>ok so here's the problem, I am following the following two railscasts:</p>
  
  <p><a href="http://railscasts.com/episodes/335-deploying-to-a-vps?autoplay=true" rel="nofollow noreferrer">deploying to a vps</a><br>
  <a href="http://railscasts.com/episodes/341-asset-pipeline-in-production?autoplay=true" rel="nofollow noreferrer">asset pipeline in production</a></p>
  
  <p>My setup:<br>
  Ubuntu Server 12.04<br>
  nginx<br>
  unicorn<br>
  ruby 1.9.3p125<br>
  rails 3.2.2</p>
  
  <p>Ad far as I can tell everything has been followed to a T (or Tea or maybe a Tee, I've never seen this phrase written down before). The sit is now running on my server but the stylesheet and javascript files are not loaded. it seems to be the same problem as <a href="https://stackoverflow.com/questions/9419230/rails-3-1-404-error-when-loading-css-files-that-are-present-in-public-assets">Rails 3.1 404 Error when loading .css files that are present in public/assets</a> or <a href="https://stackoverflow.com/questions/3410956/rails-404-error-for-stylesheet-or-javascript-files">Rails 404 error for Stylesheet or JavaScript files</a>. While the first has no answer, the latter suggests it may be a problem with the web-server not looking for static resources and perhaps shouldn't.</p>
  
  <p>Does anybody know what might be causing this?</p>
  
  <p>some facts:  </p>
  
  <ul>
  <li><p>Firstly, I was getting some nasty errors about pre-compilation and noticed that my individual css/js files had been minified into their application counterparts and so I changed their declarations in the ruby helpers to reflect this.</p></li>
  <li><p>The application works locally when I change to <code>config.serve_static_assets = true</code> in <code>config/environments/production.rb</code></p></li>
  <li><p>here is a dump of the production .log on my server</p>
  
  <pre><code>Started GET "/main" for 92.237.28.149 at 2012-07-09 23:08:02 +0100
     Processing by MainController#index as HTML
       Rendered shared/_login_form.html.erb (0.4ms)
       Rendered shared/_footer.html.erb (0.4ms)
    Rendered shared/_details_form.html.erb (7.7ms)
    Rendered main/index.html.erb within layouts/main_logged (17.1ms)
  Completed 200 OK in 21ms (Views: 20.5ms | ActiveRecord: 0.0ms)
  Compiled jquery.js  (2ms)  (pid 8253)
  Compiled jquery_ujs.js  (0ms)  (pid 8253)
  Compiled admin_user.js  (227ms)  (pid 8253)
  Compiled construction.js  (227ms)  (pid 8253)
  Compiled google-map.js  (0ms)  (pid 8253)
  Compiled jquery-1.2.6.min.js  (1ms)  (pid 8253)
  Compiled jquery-ui-personalized-1.5.2.packed.js  (0ms)  (pid 8253)
  Compiled login.js  (227ms)  (pid 8253)
  Compiled main.js  (222ms)  (pid 8253)
  Compiled menu.js  (223ms)  (pid 8253)
  Compiled order_steps.js  (225ms)  (pid 8253)
  Compiled register_user.js  (223ms)  (pid 8253)
  Compiled sprinkle.js  (0ms)  (pid 8253)   
  Compiled sticky_basket/jquery.easing.1.3.js  (0ms)  (pid 8253)
  Compiled sticky_basket/stickysidebar.jquery.js  (0ms)  (pid 8253)
  Compiled sticky_basket/stickysidebar.jquery.min.js  (0ms)  (pid 8253)
  Compiled user.js  (292ms)  (pid 8253)
  Compiled application.js  (2155ms)  (pid 8253)
  Compiled admin_user.css  (12ms)  (pid 8253)
  Compiled construction.css  (0ms)  (pid 8253)
  Compiled construction.css  (1ms)  (pid 8253)
  Compiled lightbox.css  (0ms)  (pid 8253)
  Compiled login.css  (1ms)  (pid 8253)
  Compiled main.css  (0ms)  (pid 8253)
  Compiled login.css  (1ms)  (pid 8253)
  Compiled main.css  (0ms)  (pid 8253)
  Compiled main.css  (2ms)  (pid 8253)
  Compiled menu.css  (1ms)  (pid 8253)
  Compiled menu_style.css  (0ms)  (pid 8253)
  Compiled normalise.css  (0ms)  (pid 8253)
  Compiled order_steps.css  (0ms)  (pid 8253)
  Compiled order_steps.css  (1ms)  (pid 8253)
  Compiled register_user copy.css  (0ms)  (pid 8253)
  Compiled register_user.css  (0ms)  (pid 8253)
  Compiled register_user.css  (1ms)  (pid 8253)
  Compiled tab_style.css  (0ms)  (pid 8253)
  Compiled user.css  (1ms)  (pid 8253)
  Compiled application.css  (236ms)  (pid 8253)
  Compiled jquery.js  (2ms)  (pid 8253)
  Compiled jquery_ujs.js  (0ms)  (pid 8253)
  Compiled admin_user.js  (273ms)  (pid 8253)
  Compiled construction.js  (225ms)  (pid 8253)
  Compiled google-map.js  (0ms)  (pid 8253)
  Compiled jquery-1.2.6.min.js  (1ms)  (pid 8253)
  Compiled jquery-ui-personalized-1.5.2.packed.js  (0ms)  (pid 8253)
  Compiled login.js  (269ms)  (pid 8253)
  Compiled main.js  (225ms)  (pid 8253)
  Compiled menu.js  (224ms)  (pid 8253)
  Compiled order_steps.js  (226ms)  (pid 8253)
  Compiled register_user.js  (224ms)  (pid 8253)
  Compiled sprinkle.js  (0ms)  (pid 8253)   
  Compiled sticky_basket/jquery.easing.1.3.js  (0ms)  (pid 8253)
  Compiled sticky_basket/stickysidebar.jquery.js  (0ms)  (pid 8253)
  Compiled sticky_basket/stickysidebar.jquery.min.js  (0ms)  (pid 8253)
  Compiled user.js  (224ms)  (pid 8253)
  Compiled application.js  (2096ms)  (pid 8253)
  Compiled admin_user.css  (12ms)  (pid 8253)
  Compiled construction.css  (0ms)  (pid 8253)
  Compiled construction.css  (1ms)  (pid 8253)
  Compiled lightbox.css  (0ms)  (pid 8253)
  Compiled login.css  (1ms)  (pid 8253)
  Compiled main.css  (0ms)  (pid 8253)
  Compiled login.css  (1ms)  (pid 8253)
  Compiled main.css  (0ms)  (pid 8253)
  Compiled main.css  (1ms)  (pid 8253)
  Compiled menu.css  (2ms)  (pid 8253)
  Compiled menu_style.css  (0ms)  (pid 8253)
  Compiled normalise.css  (0ms)  (pid 8253)
  Compiled order_steps.css  (0ms)  (pid 8253)
  Compiled order_steps.css  (1ms)  (pid 8253)
  Compiled register_user copy.css  (0ms)  (pid 8253)
  Compiled register_user.css  (0ms)  (pid 8253)
  Compiled register_user.css  (1ms)  (pid 8253)
  Compiled tab_style.css  (0ms)  (pid 8253)
  Compiled user.css  (1ms)  (pid 8253)
  Compiled application.css  (179ms)  (pid 8253)
  
  
  Started GET "/main" for 92.237.28.149 at 2012-07-09 23:15:00 +0100
  Processing by MainController#index as HTML   
    Rendered shared/_login_form.html.erb (1.2ms)
    Rendered shared/_footer.html.erb (1.1ms)
    Rendered shared/_details_form.html.erb (15.5ms)
    Rendered main/index.html.erb within layouts/main_logged (80.9ms)
  Completed 200 OK in 142ms (Views: 140.4ms | ActiveRecord: 0.0ms)
  
  
  Started GET "/main" for 92.237.28.149 at 2012-07-09 23:33:54 +0100
  Processing by MainController#index as HTML
    Rendered shared/_login_form.html.erb (1.2ms)
    Rendered shared/_footer.html.erb (1.1ms)
    Rendered shared/_details_form.html.erb (15.6ms)
    Rendered main/index.html.erb within layouts/main_logged (80.7ms)
  Completed 200 OK in 142ms (Views: 140.0ms | ActiveRecord: 0.0ms)
  </code></pre></li>
  </ul>
  
  <p>As you can see there are no more complaints about pre-compilation</p>
  
  <p>here is the html generated</p>
  
  <pre><code>  &lt;title&gt;HTML Snippet&lt;/title&gt;
    &lt;link href="/assets/application-dd445a707b7e96c914afd14bf1f02bbc.css" media="screen" rel="stylesheet" type="text/css" /&gt;
    &lt;script src="/assets/application-def3878140cda305cb0ca5ef745fd758.js" type="text/javascript"&gt;&lt;/script&gt;
    &lt;script src="http://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js" type="text/javascript"&gt;&lt;/script&gt;
    &lt;script src="http://cloud.github.com/downloads/malsup/cycle/jquery.cycle.all.latest.js" type="text/javascript"&gt;&lt;/script&gt;
  </code></pre>
  
  <p>These links generate an nginx 404 if I click on them but if i change the url to
  <code>http://&lt;ipaddress&gt;/public/assets/application-dd445a707b7e96c914afd14bf1f02bbc.css</code> i get a rails generated <code>The page you were looking for doesn't exist.</code></p>
  
  <p>And here is the important (I think) contents of /public/assets on my server</p>
  
  <pre><code>application-7c90c01effcf9d8593e28e4c4b716ac2.css
  application-7c90c01effcf9d8593e28e4c4b716ac2.css.gz
  application.css
  application.css.gz
  application-dd445a707b7e96c914afd14bf1f02bbc.css
  application-dd445a707b7e96c914afd14bf1f02bbc.css.gz
  application-def3878140cda305cb0ca5ef745fd758.js
  application-def3878140cda305cb0ca5ef745fd758.js.gz
  application.js
  application.js.gz
  </code></pre>
  
  <p>finally, the area that I'm not so clear on and just so its all covered, here are the files used in the railscast for configuration of capistrano, nginx and unicorn:</p>
  
  <p>I have uncommented the <code>load 'deploy/assets'</code> in capfile</p>
  
  <p>deploy.rb</p>
  
  <pre><code>require "bundler/capistrano"
  
  server "92.237.28.149", :web, :app, :db, primary: true
  
  set :application, "little_oven_deploy"
  set :user, "daz"
  set :deploy_to, "/home/#{user}/apps/#{application}"
  set :deploy_via, :remote_cache
  set :use_sudo, false
  
  set :scm, "git"
  set :repository, "git@bitbucket.org:DanBaldwin/little_oven_deploy.git"
  set :branch, "master"
  
  default_run_options[:pty] = true
  ssh_options[:forward_agent] = true
  
  after "deploy", "deploy:cleanup" # keep only the last 5 releases
  
  namespace :deploy do
    %w[start stop restart].each do |command|
      desc "#{command} unicorn server"
      task command, roles: :app, except: {no_release: true} do
        run "/etc/init.d/unicorn_#{application} #{command}"
      end
    end
  
    task :setup_config, roles: :app do
      sudo "ln -nfs #{current_path}/config/nginx.conf /etc/nginx/sites-enabled/#{application}"
      sudo "ln -nfs #{current_path}/config/unicorn_init.sh /etc/init.d/unicorn_#{application}"
      run "mkdir -p #{shared_path}/config"
      put File.read("config/database.example.yml"), "#{shared_path}/config/database.yml"
      puts "Now edit the config files in #{shared_path}."
    end
    after "deploy:setup", "deploy:setup_config"
  
    task :symlink_config, roles: :app do
      run "ln -nfs #{shared_path}/config/database.yml #{release_path}/config/database.yml"
    end
    after "deploy:finalize_update", "deploy:symlink_config"
  
    desc "Make sure local git is in sync with remote."
    task :check_revision, roles: :web do
      unless `git rev-parse HEAD` == `git rev-parse origin/master`
        puts "WARNING: HEAD is not the same as origin/master"
        puts "Run `git push` to sync changes."
        exit
      end
    end
    before "deploy", "deploy:check_revision"
  end
  </code></pre>
  
  <p>nginx.conf</p>
  
  <pre><code>upstream unicorn {
    server unix:/tmp/unicorn.little_oven_deploy.sock fail_timeout=0;
  }
  
  server {
    listen 80 default deferred;
    # server_name example.com;
    root /home/deployer/apps/blog/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;
    }
  
    error_page 500 502 503 504 /500.html;
    client_max_body_size 4G;
    keepalive_timeout 10;
  }
  </code></pre>
  
  <p>unicorn.rb  </p>
  
  <pre><code>root = "/home/daz/apps/little_oven_deploy/current"
  working_directory root
  pid "#{root}/tmp/pids/unicorn.pid"
  stderr_path "#{root}/log/unicorn.log"
  stdout_path "#{root}/log/unicorn.log"
  
  listen "/tmp/unicorn.little_oven_deploy.sock"
  worker_processes 2
  timeout 30
  </code></pre>
  
  <p>unicorn_init.sh</p>
  
  <pre><code>#!/bin/sh
  ### BEGIN INIT INFO
  # Provides:          unicorn
  # Required-Start:    $remote_fs $syslog
  # Required-Stop:     $remote_fs $syslog
  # Default-Start:     2 3 4 5
  # Default-Stop:      0 1 6
  # Short-Description: Manage unicorn server
  # Description:       Start, stop, restart unicorn server for a specific application.
  ### END INIT INFO
  set -e
  
  # Feel free to change any of the following variables for your app:
  TIMEOUT=${TIMEOUT-60}
  APP_ROOT=/home/daz/apps/little_oven_deploy/current
  PID=$APP_ROOT/tmp/pids/unicorn.pid
  CMD="cd $APP_ROOT; bundle exec unicorn -D -c $APP_ROOT/config/unicorn.rb -E production"
  AS_USER=daz
  set -u
  
  OLD_PIN="$PID.oldbin"
  
  sig () {
    test -s "$PID" &amp;&amp; kill -$1 `cat $PID`
  }
  
  oldsig () {
    test -s $OLD_PIN &amp;&amp; kill -$1 `cat $OLD_PIN`
  }
  
  run () {
    if [ "$(id -un)" = "$AS_USER" ]; then
      eval $1
    else
      su -c "$1" - $AS_USER
    fi
  }
  
  case "$1" in
  start)
    sig 0 &amp;&amp; echo &gt;&amp;2 "Already running" &amp;&amp; exit 0
    run "$CMD"
    ;;
  stop)
    sig QUIT &amp;&amp; exit 0
    echo &gt;&amp;2 "Not running"
    ;;
  force-stop)
    sig TERM &amp;&amp; exit 0
    echo &gt;&amp;2 "Not running"
    ;;
  restart|reload)
    sig HUP &amp;&amp; echo reloaded OK &amp;&amp; exit 0
    echo &gt;&amp;2 "Couldn't reload, starting '$CMD' instead"
    run "$CMD"
    ;;
  upgrade)
    if sig USR2 &amp;&amp; sleep 2 &amp;&amp; sig 0 &amp;&amp; oldsig QUIT
    then
      n=$TIMEOUT
      while test -s $OLD_PIN &amp;&amp; test $n -ge 0
      do
        printf '.' &amp;&amp; sleep 1 &amp;&amp; n=$(( $n - 1 ))
      done
      echo
  
      if test $n -lt 0 &amp;&amp; test -s $OLD_PIN
      then
        echo &gt;&amp;2 "$OLD_PIN still exists after $TIMEOUT seconds"
        exit 1
      fi
      exit 0
    fi
    echo &gt;&amp;2 "Couldn't upgrade, starting '$CMD' instead"
    run "$CMD"
    ;;
  reopen-logs)
    sig USR1
    ;;
  *)
    echo &gt;&amp;2 "Usage: $0 &lt;start|stop|restart|upgrade|force-stop|reopen-logs&gt;"
    exit 1
    ;;
  esac
  </code></pre>
  
  <p>unicorn_init.sh is also chmod +x.</p>
  
  <p>Sorry for the potential overload of information guys but if it helps give you a snapshot of my issue, it helps to get a diagnosis and any help is much appreciated.</p>
  
  <p>Thanks in advance</p>