How we used Amazon Cloudfront as a CDN with Rails assets

Amazon Cloudfront is a great way of serving your assets for your site from localised buckets.

Firstly you need to set up a new distribution from your amazon CloudFront console here.

Associate your distribution with a current bucket, or alternatively with a new bucket name, but if you do this you will need to create the bucket on your s3 account so it is associated with it. I have created a new one and called it d50-assets

amazon aws console 300x196 How we used Amazon Cloudfront as a CDN with Rails assets

Enter your cname values, you will need 4 for the standard cnames with Rails assets. Mine are:

assets0.dynamic50.com
assets1.dynamic50.com
assets2.dyanmic50.com
assets3.dynamic50.com

And create the distribution….

When the distribution is created you will be assigned a domain name for you distribution. In my case this is d1i6gs7snlaxix.cloudfront.net
So now your DNS server needs to be configured for your domain. In my case this is from within my slicehost console.

I set the following as CNAMES:

assets0.dynamic50.com
assets1.dynamic50.com
assets2.dyanmic50.com
assets3.dynamic50.com

with a value of :

my_unique_cloudfront_domain.cloudfront.net

If you are on slicehost, don’t forget the full stop (.) after the value so it doesn’t auto-complete to

my_unique_cloudfront_domain.cloudfront.net.yourhost.com

Using an s3 access tool (I use s3fox), log in to you s3 account and upload all of your assets (ie everything inside your public directory) to the bucket.

Make sure the bucket permissions are set correctly so that it is world readable.

amazon aws 300x251 How we used Amazon Cloudfront as a CDN with Rails assets

Now you are ready to make the changes on your Rails app.

Go to the production environment file and set:

ActionController::Base.asset_host = "http://assets%d.myhost.com"

cap deploy and your asset host will be working!

On a side note, I don’t want my javascripts or css served by this asset host, so to turn this off replace the above line with the following line:

ActionController::Base.asset_host = Proc.new { |source|
  unless source.starts_with?('/stylesheets' || '/javascripts')
    "http://assets#{rand(4)}.myhost.com"
  end
}

3 Comments

RSS feed for comments on this post. TrackBack URL

  1. Paul Hepworth — October 16, 2010

    Thanks for the post…. there is one thing thats a bit strange: I tried to do what you were doing and your asset_host code has a bug.

    When using the code that you have above, the same image/asset is served from two different servers and the browser has to download them a second time without hitting its cache.

  2. admin — November 2, 2010

    Hi Paul,
    Thanks for your comment
    It’s been a while since I tried this! Could you suggest a fix for this?

  3. chimbo — June 8, 2011

    I believe theres a solution in this post

    http://www.alfajango.com/blog/caching-zipping-and-cdn-for-a-rails-app/

    [“https://yourcloudfrontdist0.cloudfront.net”,
    https://yourcloudfrontdist1.cloudfront.net”,
    https://yourcloudfrontdist2.cloudfront.net”,
    https://yourcloudfrontdist3.cloudfront.net” ][source.hash % 4]

    Which will use the asset host based on the modulus 4 of the source

Leave a comment

Preview: