Ask A Question

Notifications

You’re not receiving notifications from this thread.

Amazon Cloudfront CDN for Rails Asset Pipeline & Webpacker Discussion

Warning: when using a load-balanced production configuration, this configuration can result in intermittently broken assets. The problem occurs when traffic arrives during a reload that includes fresh assets. If care isn't taken, it's possible for a browser to request assets that aren't yet available from every backend.

The CDN may then cache a 404 for that asset, with horrible results. A typical symptom is missing CSS and JS for all subsequent visitors. The recovery from this breakage may be painfully slow, because cache invalidation in Cloudfront is a) fiddly and b) takes minutes/hours to complete. You can fine-tune Cloudfront to not cache 404s, but serving them to any user at all is simply unacceptable in production.

To avoid all this, you must ensure that fully precompiled assets are available from all CDN origins prior to any reload. There's several ways to achieve that, but I'll generally configure a sync to S3 in the before_restart hook; the CDN then uses the bucket as origin. You could also use a CI/CD pipeline, or blue/green deploys, or a shared public/ folder, or carefully choreographed rolling reloads.

Reply

Great points! 👍

Reply

That's a feature to be added to Hatchbox :)

Reply

AND a future episode :)

Reply

The CDN should not cache a 404 response if cache control headers are set correctly right?

Reply

Chris, hoping for the episode on using a CDN with user uploaded content, we use CarrierWave (and plan to keep using because it's years beyond ActiveStorage in features) and that's the biggest number of assets (and the heaviest assets) we have to serve.

Reply

Hi how can i download the video? I thought I can also download video after i subscribe

Reply

You can also put a CDN directly in front of your application for serving dynamic content, as well. Talking about CloudFront specifically, one benefit of doing this includes reduced latency because AWS maintains persistent connections in their internal network much longer. So I usually have two CDNs configured: one for static assets, and one for dynamic requests.

Reply

How would we go about setting this up to work for our S3 bucket and active storage. Im assuming would need to adjust the storage.yml file to point to the Cloudfront domain right? But would that mess up the the upload with activestorage?

In the storage.yml can you just add in the endpoint to the amazon configuration like this:

amazon:
  service: S3
  access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %>
  secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %>
  region: us-west-2
  bucket: living-recipe-images
    endpoint: 'abcdefg12345678.cloudfront.net'
Reply

I have issues with my loading my fonts, what do I do?

(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-400-normal-c3d2d5ea9c4f415771b93268b077c0e1d7518849fffdea083a35e363a6d3e3bb.woff2' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
(index):533 GET https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-400-normal-c3d2d5ea9c4f415771b93268b077c0e1d7518849fffdea083a35e363a6d3e3bb.woff2 net::ERR_FAILED
(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/fonts/glyphicons-halflings-regular.woff' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
(index):533 GET https://d3r405gy40gjfe.cloudfront.net/assets/fonts/glyphicons-halflings-regular.woff net::ERR_FAILED
(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-300-normal-47a4b25fec97e13de8dc5700c5be38c18da9936e1b3bbece603a1bc27ee4c754.woff2' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
(index):533 GET https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-300-normal-47a4b25fec97e13de8dc5700c5be38c18da9936e1b3bbece603a1bc27ee4c754.woff2 net::ERR_FAILED
(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-500-normal-c6130453c6dfd8a6059a43dd525e673f2ed2fe77c9cd52b6cc3914ff4dcd5872.woff2' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
(index):533 GET https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-500-normal-c6130453c6dfd8a6059a43dd525e673f2ed2fe77c9cd52b6cc3914ff4dcd5872.woff2 net::ERR_FAILED
(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-400-italic-fdb66bcef428b21c195a1f29fd46b0c5c5f3a9982ea41f9c84a8cc5273737637.woff2' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
(index):784 GET https://d3r405gy40gjfe.cloudfront.net/assets/woff2/geogrotesque-400-italic-fdb66bcef428b21c195a1f29fd46b0c5c5f3a9982ea41f9c84a8cc5273737637.woff2 net::ERR_FAILED
(index):1 Access to font at 'https://d3r405gy40gjfe.cloudfront.net/assets/woff/geogrotesque-400-normal-8c71b25d9aff001fea5229583ad079b43a236c37dbf22174ef1e4a559371a163.woff' from origin 'https://test.mywebsite.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Reply

how did the images/css/assets get into Cloudflare in the first place? You set up the CDN, you tweak some settings for production and .... well, I can't tell.

Reply

That's the cool part. When you configure the backend, it will accept all requests and then ask your app (the backend) for the files and send them back. It saves them in the CDN so that next request, it doesn't have to ask your app again and can serve it up immediately. It just sits in between the user and the app as a proxy.

Reply

so in the context of Rails and Heroku, how does the backend of my app know to send the files to Cloudfront, esp a file which might only rarely be requested? For example, a user's avatar which might only be shared if they ever log in again -- compared to a CSS file which may well be referenced on most every request

Reply

I'm talking about "how do the files get into CF in the first place" rather than "how does my app serve them from CF once they are there"

Reply

Like I mentioned before, CF is a proxy so it passes the requests to Rails. Rails serves up files just like it always does. Nothing special.

Reply

For some reason Cloudfront sends files with "text/html" where as the origin server is sending it correctly.
I am getting a warning from chrome Resource interpreted as Stylesheet but transferred with MIME type text/html, and browser has to do a 301 redirect to fetch the resource again.

Screenshots:

  1. Redirect - https://user-images.githubusercontent.com/749134/92719213-760abc80-f380-11ea-8732-3337d5f00534.jpg
  2. Warning - https://user-images.githubusercontent.com/749134/92719232-7c993400-f380-11ea-8a16-839a49913b63.jpg
Reply
Join the discussion
Create an account Log in

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

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

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