Skip to main content

rails5 + heroku + cloudfront + fonts

Gems / Libraries • Asked by Sean M

I tried to configure a rails5 app (deployed on heroku) with cloudfront for assets and fonts. I could make it work for the assets, then I tried to add the config for the fonts as well, but I just screwed up everything and none of them works.

At the moment for the assets I get 404 error:

Failed to load resource:  xzy.cloudfront/assets/application-12341234.css the server   responded with a status of 404 ()

For the prev version when the assets worked but the fonts didn't, I got this error (I don't remember what was the diff between the 2 setup):

Access to Font at 'https://xyz.cloudfront.net/assets/fontawesome-webfont-7dacf83f51179de8d7980a513e67ab3a08f2c6272bb5946df8fd77c0d1763b73.woff2' from origin 'https://xyz.cloudfront.net' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://xzy.herokuapp.com' is therefore not allowed access.

I didn't really understand the problem because I thought I had everything properly configured:

production.rb

config.action_controller.asset_host = ENV['CLOUDFRONT_URL']
config.static_cache_control = 'public, max-age=31536000'

initializes/cors.rb (added the cors gem)

Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
  origins '*'
  resource '/assets/*', headers: :any, methods: [:get]
  end
end

I likely didn't mess up the basic cloudfront config, because it was working before I started tweaking with the fonts. The behavior path pattern is set to default and it's connected to the herokuapp. The problem could be that the forwarded headers in the behavior are set like this:

Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age
Origin

As far as I know rails5 works with 12factors out of the box, so I don't have to add config.serve_static_assets = true if my RAILS_SERVE_STATIC_FILES env var is set to enabled (which happens automatically with heroku).

What did I miss? How can I make this work again?


Yo Szilard! It's been a while since I've setup Cloudfront especially with fonts.

Did you make any progress on this?


Hey Chris,

I didn't :(. This (https://github.com/equivalent/scrapbook2/blob/master/archive/blogs/2016-09-cors-rails-assets-cdn-heroku.md) seems to be quiet a resource, but didn't solve the problem with rails 5. If I set the allowed headers to my cloudfront distribution name then I get this error:

Access to Font at 'https://b33ef7kfsqfs9e.cloudfront.net/assets/fontawesome-webfont-7dacf83f51179de8d7980a513e67ab3a08f2c6272bb5946df8fd77c0d1763b73.woff2' from origin 'https://b33ef7kfsqfs9e.cloudfront.net' has been blocked by CORS policy: The 'Access-Control-Allow-Origin' header has a value 'https://b33ef7kfsqfs9e.cloudfront.net' that is not equal to the supplied origin. Origin 'https://abcdef-staging.herokuapp.com' is therefore not allowed access.

This error is super weird because basically says https://b33ef7kfsqfs9e.cloudfront.net != https://b33ef7kfsqfs9e.cloudfront.net.

I have a few workarounds in mind like excluding fonts from cloudfront or uploading fonts to S3 (of course with cloudfront pointing to bucket) and adding the new source path in css files, but I would rather do the proper fix with allowed headers.


I thought I would put my two cents in on this issue. I recently tried to use Font Awesome with Heroku and CloudFront on Rails 5 and faced a similar problem. Here's what I did to get it to work:

Installed rack-cors

gem 'rack-cors'

Configured rack-cors

config/initializers/rack-cors.rb

if defined? Rack::Cors
  Rails.configuration.middleware.insert_before 0, Rack::Cors do
    allow do
      origins %w[
        https://example.com
         http://example.com
        https://www.example.com
         http://www.example.com
        https://example.herokuapp.com
         http://example.herokuapp.com
      ]
      resource '/assets/*'
    end
  end
end

I preferred not to leave it wide open and just use the domains I knew I would hit it with.

Configure CloudFront

  • https://console.aws.amazon.com/cloudfront/home#distributions
  • select the distribution
  • click Distribution Settings
  • go to the Behaviors tab
  • select the behavior (there will probably be only one)
  • Click Edit
  • Forward Headers: Whitelist
  • Whitelist Headers: Select Origin and click Add >>
  • Paste the following into the custom box one at a time and click Add Custom>>
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Max-Age

After messing with this for over 6 hours, I think I messed it up even more. The last thing I did that finally made these settings stick was invalidate the CloudFront cache.

You can explicitly invalidate cached assets by going to the CloudFront distribution's Invalidations tab and creating an invalidation for *. I guess CloudFront cache sticks around longer than I had thought. This step took about 10 minutes. Yours might take less.


Awesome post, thanks for sharing Michael! :D I need to do an episode on Cloudfront sometime.


Nice stuff, this helped me out alot. Big thanks


Login or Create An Account to join the conversation.

Subscribe to the newsletter

Join 27,623+ developers who get early access to new screencasts, articles, guides, updates, and more.

    By clicking this button, you agree to the GoRails Terms of Service and Privacy Policy.

    More of a social being? We're also on Twitter and YouTube.