A gotcha with Active Storage and Cloudflare

Rails 5.2 introduced Active Storage and it's pretty awesome. I'd used paperclip from the @thoughtbot folks for a long time, but file uploading is a requirement for just about any site these days so it might as well be part of the core. Now it is.

Well, if you happened to implement Active Storage into your Rails app and happen to be behind a Cloudflare CDN then you might run into a little issue. Namely, your images will stop showing up after 5 minutes. What?! Weird, right?

The discovery was made here with the help of some other friendly githubbers. I'm gathering the important stuff below if you just want the fix.

The Problem

If you are using Cloudflare for some of their services and have never touched the cache settings, you'll probably run into this problem with Active Storage. It's also entirely possible that this issue could happen with other CDNs, but your mileage may very.

Cloudflare, in its attempt to be helpful, was caching a little too hard for everything to work. When you upload a file via Active Storage to S3 you're going to get back a reference url from url_for(user.avatar). That reference URL is responsible for redirecting the request to the final resting place of the uploaded file (S3, Azure, Google Cloud, etc.)

According to the Rails docs The redirection has an HTTP expiration of 5 min.. It's after those 5 minutes that we run into our issue. Instead of getting a cache control header on the blob request like

Cache-Control: max-age=300, private

we ended up getting

Cache-Control: public, max-age=14400

which was responsible for redirecting to an expired S3 url. This was Cloudflare trying to do its job, but it's not what we want.

The Solution

The solution I'm using is to tell Cloudflare to ignore a url pattern that resembles our blob url requests. So let's do that.

  1. Log into Cloudflare
  2. Select the domain in question
  3. Click Page Rules from the menu at the top
  4. Click Create Page Rule
  5. Enter your wildcard blob path. It should resemble: http://example.com/rails/active_storage/blobs/*
  6. Chose a setting of Cache Level and set it to Bypass
  7. Click Save and Deploy

Example for my site:

Page rule in Cloudflare

This is going to tell Cloudflare to ignore the redirect request. Considering that request is just a redirection and not a heavy file it shouldn't be an enormous performance loss to ignore any form of caching.

This method is also a nice strategy if you have sophisticated caching set up already as it only pertains to Active Storage stuff and doesn't affect anything else you may already have.

Conclusion

Hopefully it helps solve the mystery that landed you here, disappearing files. It took a while to pinpoint the problem, but I think this solution ends up being a reasonable method in the end.