Why is application.css working locally but 404 on production server?
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
/example/current/public/assets/application-af01d6a4cd32bfcf9b8c41fa5fd1f1501cba6e3953ea8ff518309d0b7a8614c9.css
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!
/etc/nginx/sites-enabled/example.com
server {
listen 80;
listen [::]:80;
server_name example.com;
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;
}
}
config/deploy.rb
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")
end
end
end
desc 'Restart application'
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute :touch, release_path.join('tmp/restart.txt')
end
end
after :publishing, 'deploy:restart'
after :finishing, 'deploy:cleanup'
end
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. https://guides.rubyonrails.org/configuring.html#results-of-config-load-defaults