All threads / Why is application.css working locally but 404 on production server?
Ask A Question


You’re not receiving notifications from this thread.

Why is application.css working locally but 404 on production server?

Thomas Bush asked in General

My css works perfect locally, but I get a 404 error for applicaiton.css once deployed. I generated my base app using Jumpstart free version. I confirmed app css is generated on the server in the public assests folder

My nginx config and capistrano deploy both follow the webpacker docs: nginx serves static assets and packs, cap deploy ensures yarn is installed (each included below). My config/webpacker.yml is unchanged. I have seen dozens of issues where people are facing similar situations, but the solutions never seem to apply in my case, I have been stuck on this issue for 2 days now, hoping someone notices something obvious that I missed as I have been staring at it for too long. I appreciate any help or insight you can provide!


server {
  listen 80;
  listen [::]:80;

  root /home/deploy/example/current/public;

  passenger_enabled on;
  passenger_app_env production;

  location /cable {
    passenger_app_group_name example_websocket;
    passenger_force_max_concurrent_requests_per_process 0;

  location = /favicon.ico { access_log off; log_not_found off; }
  location = /robots.txt  { access_log off; log_not_found off; }

  # Allow uploads up to 100MB in size
  client_max_body_size 100m;

  location ~ ^/(assets|packs) {
    expires max;
    gzip_static on;
    add_header Cache-Control public;

  location /healthcheck {
    access_log off;
    return 200;
    add_header Content-Type text/plain;


lock "~> 3.13.0"
require 'capistrano-db-tasks'

set :application, 'example'

set :deploy_via, :remote_cache
set :deploy_to, '/home/deploy/example'
set :branch, ENV['BRANCH'] if ENV['BRANCH']

set :linked_files, %w{config/database.yml config/master.key}
append :linked_dirs, 'log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'public/packs', '.bundle', 'node_modules'

set :db_local_clean, true
set :db_remote_clean, true

set :keep_releases, 3
set :keep_assets, 3

before "deploy:assets:precompile", "deploy:yarn_install"
namespace :deploy do
  desc "Run rake yarn install"
  task :yarn_install do
    on roles(:web) do
      within release_path do
        execute("cd #{release_path} && yarn install --silent --no-progress --no-audit --no-optional")

  desc 'Restart application'
  task :restart do
    on roles(:app), in: :sequence, wait: 5 do
      execute :touch, release_path.join('tmp/restart.txt')

  after :publishing, 'deploy:restart'
  after :finishing, 'deploy:cleanup'

Does the route the browser is looking for match the filename assets/application-af01d6a4cd32bfcf9b8c41fa5fd1f1501cba6e3953ea8ff518309d0b7a8614c9.css

Those files are served up directly through NGINX, not Rails, so that's where you'd want to be looking.

Well that's a great point.

The missing 404 error is for is for applicaiton.css, and the generated file on server is the fingerprinted file. I guess I don't quite understand why the requested file would be anything other than the fingerprinted file as I am just using the standard rails include:

<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>

Rails will always use fingerprinted files in production, nothing fancy there. You just need to make sure the URL it's looking for matches a file in your current deployment directory on the server.

Thanks for all the help Chris, I ended up figuring this out after you pointed me in the right direction.

In my specific case I needed to set in app/config/environments/production.rb:

config.assets.digest = true

I am still a bit confused as to why this was required as the rails docs state config.assets.digest defaults to true, as a result I have never explicitly set this value in any past rails apps.

from the current rails docs

Fingerprinting is enabled by default for both the development and production environments. You can enable or disable it in your configuration through the config.assets.digest option.

In any case, I really appreciate your help as always!

The defaults are also manipulated by the load_defaults method which can tell Rails to use the defaults from a specific version of Rails. Could be something with that maybe, I'm not sure.

Join the discussion

Want to stay up-to-date with Ruby on Rails?

Join 69,840+ developers who get early access to new tutorials, screencasts, articles, and more.

    We care about the protection of your data. Read our Privacy Policy.

    logo Created with Sketch.

    Screencast tutorials to help you learn Ruby on Rails, Javascript, Hotwire, Turbo, Stimulus.js, PostgreSQL, MySQL, Ubuntu, and more. Icons by Icons8

    © 2023 GoRails, LLC. All rights reserved.