CloudFront is a Content Delivery Network (CDN), powered by Amazon. CloudFront is used for hosting assets over a different region and serving these assets from the nearest server for any particular request.
While deploying the application all the files including Javascript, CSS, Fonts and other files reside on one server. If we want to reduce the load time for any page and improve overall response time, we need to think about how to reduce the number of requests to our application server. To tackle this issue, we can forward asset retrieval requests to a separate asset hosting server. In that way, we are segregating our static assets from the application. Also, we are going to host our images on file storage like Amazon S3 as a content delivery network or content distribution network (CDN). In that case, our resources come from Amazon S3 and all the asset retrieval requests will go to Amazon S3.
Now, we are happy with this famous third-party service but one question may arise where our storage server is located and when the request comes from a different region, does this storage service meet our expectations in terms of the minimum load time of resources? So we consider again how we can achieve this and how we are going to use Amazon CloudFront service to minimize the load time of resources along with resource distribution.
But we can make it work by following CORS standards. We will see an example of CORS implementation for Amazon S3 and CloudFront as our assets distribution service.
When a cross-origin request is initiated, it includes the request origin in its header. The value of this header is the domain that serves the page. For example, your request for Nascenia and it's all assets are hosted at assets.nascenia.com. If we want the browser to implement CORS between Nascenia and assets.nascenia.com, the following request header needs to be sent to nascenia.com:
Origin: http://assets.nascenia.com
If nascenia.com allows the request, it sends an Access-Control-Allow-Origin key in its response header and the value will be:
Access-Control-Allow-Origin: http://assets.nascenia.com
If the server does not allow the cross-origin request, the browser will return an error. The value of the header indicates which origin sites are allowed. To allow access from all domains, a server can send the following response header:
Access-Control-Allow-Origin: *
In this case, across request was initiated from assets.nascenia.com to nascenia.com and nascenia.com allowed access for all domains.
The steps to set up CloudFront distribution will be as follows:
Step-1: Login to your Amazon console and go to CloudFront service, which will be like below:
And click to Create Distribution to go to the next step.
Step-2: In this step, you need to select the type of delivery method. In our case, of course, it is web type and it remains selected by default.
Step 3: In this step, we set up our origin which is responsible for storing our assets. Before going any further from this, I assume that you already have an Amazon S3 account and you stored your assets on that storage service.
If you have a bucket at Amazon S3, then you will see that there is a text field named Origin Domain Name with some bucket names and you are able to see these names when you click on this box and select your intended bucket like xyz.s3.amazonaws.com as a dropdown list if you have multiple buckets. This step will be like below:
Also, other fields will remain blank as the default value and you can edit it later if necessary. It takes an hour for this distribution to come online.
Now, we configure our application to serve assets from this distribution. We use asset_sync gem to synchronize our precompiled assets during slug compilation with Amazon S3. For this, we need to follow instructions from this gem asset_sync.
Here are the steps:
Step-1: Enable the user-env-compile functionality by executing the following command in the terminal
heroku labs:enable user-env-compile -a myapp
Step-2: Add the gem in: assets group in your Gemfile
group :assets do gem 'asset_sync' end
Step 3: Configure config/environments/production.rb to use Amazon S3 as the asset host and ensure precompiling is enabled.
#config/environments/production.rb config.action_controller.asset_host = "//#.s3.amazonaws.com"
Also, ensure the following are set (in production .rb or application.rb)
config.assets.digest = true. config.assets.enabled = true.
Additionally, if you depend on any configuration that is set up in your initializers you will need to ensure that you set the following option (in production.rb or application.rb):
config.assets.initialize_on_precompile = true
Step-4: Now, we set the environment variables that will help us in the asset synchronization process. Add your configuration details to Heroku.
heroku config:add AWS_ACCESS_KEY_ID=xxxx heroku config:add AWS_SECRET_ACCESS_KEY=xxxx heroku config:add FOG_DIRECTORY=xxxx heroku config:add FOG_PROVIDER=AWS
You may also define different keys depending upon your context. To do so, we can create a YAML file by running the following command:
rails g asset_sync:install --use-yml --provider=AWS
The generator will create a YAML file at config/asset_sync.yml and modify it to your own requirements if needed.
Now, we have completed all the process except one configuration. We have not added any CloudFront link that will use for asset distribution. You will be able to collect it from CloudFront using this AWS console with proper credentials. Then select your distribution -> Distribution Settings -> General tab -> Domain Name, copy the domain name from here and put it into production. rb as an asset_host.
So, go to config/environments/production.rb file and modify the following settings once again:
#config/environments/production.rb config.action_controller.asset_host = "//xyz.cloudfront.net"
After completing the process, browse your site and observe the loading speed of your application.
But you may notice that some items are not loading properly like font awesome or any other custom fonts! It is due to CORS and you need to permit these resources to get access via CloudFront.
So we need to allow our Amazon S3 assets to access via CloudFront. To do this, we need to add the filter to set Access-Control-Allow-Origin in the application controller.
For Rails 2.3.8
class ApplicationController < ActionController::Base protect_from_forgery after_filter :allow_cross_domain_access def allow_cross_domain_access response.headers["Access-Control-Allow-Origin"] = "*" response.headers["Access-Control-Allow-Methods"] = "*" end end
For Rails 3.1
class ApplicationController < ActionController::Base protect_from_forgery after_filter :allow_cross_domain_access def allow_cross_domain_access headers['Access-Control-Allow-Origin'] = '*' headers['Access-Control-Request-Method'] = '*' end end
For Rails 4
In config/application.rb:
config.action_dispatch.default_headers =
Also, you need to allow it via Amazon S3. To do go to:
amazon s3 console -> select your intended s3 bucket -> properties -> Add more permissions -> Add bucket policy
A popup window will open to give bucket CORS permissions. There will be a link to see sample permissions or you may put this below configuration:
* GET 3000 *
Now all the setup is completed and you are ready for CloudFront distribution without any issue. That's it!
Contributor: Naim Rajib, Software Engineer, NasceniaMore to Explore
The Quest for Knowledge Continues. Fuel Your Curiosity.




