- Gzip compression should be turned on for HTTP 1.0
- If the Last-Modified header is present files may not be updated correctly at the expire time
I have therefore documented my setup here in case someone else could find it useful.
To use Amazon Cloudfront the way described here your Rails app must be at version 3.1(or higher) and must be using the Rails Asset Pipeline. You also need an account with Amazon Web Services.
Configuring your Nginx webserver
Regardless of using Cloudfront or not I prefer to serve assets from a separate subdomain like for instance assets.example.com. This just feels cleaner to me and makes it easy to ensure that only assets are served through Cloudfront. Here is what the Nginx configuration looks like:
The configuration explained:
- allow all Allow access to everything inside the assets directory, everything else is blocked by the deny all statement above.
- gzip_http_version 1.0 If you do not include this setting Cloudfront will NOT serve gzipped versions of the files. As a result the files you are serving will be significantly larger, potentially nullifying the speed you gain from using Cloudfront!
- expires 365d Indicates that the assets should be cached for one year. So browsers that downloads the assets should not ask for them again before one year has passed. It is my understanding that Cloudfront also uses this to decide how long to store the assets. Normally the assets files are small so the cost of storing them for one year should be minimal, but should you have very large assets that are changed frequently you may want to consider a lower value here.
- add_header Last-Modified “” This removes the Last-Modified header. We have experienced that when the Last-Modified header is present the file may not be updated correctly when the expires time is reached. This caused the browser to make if-modified requests for the asset every time the page was loaded. Not sure why this is happening, but apparently this header should be removed anyway as, according to among others the Asset Pipeline Rails Guide, it’s presence may cause some browsers to request the file again before the expires time is reached.
- add_header Cache-Control public This sets Cache-Control to public. This indicates that the assets can be stored in public caches, like for instance in a proxy.
Note that to add the settings related to gzip you have to enable gzip for Nginx in the first place. You do this in the nginx.conf file, and here are the settings that are working for me:
This configuration should be good also for apps where Cloudfront is not used. The only setting specific to Cloudfront is gzip_http_version 1.0 so this can be removed.
Creating the Cloudfront distribution
Next step is to create the Cloudfront distribution, we are going to go with the defaults of no HTTPS and no logging. Sign in to the AWS Management Console, then click “Create distribution”:
Select “Custom origin”, enter the subdomain configured above and click Continue:
On the next screen enter the domain that should be used to access the assets, then Click continue:
Your distribution has now been created, note that it may take a few minutes before it is ready.
The distribution you created has a domain name that looks like xxxxxxxxxxxxxx.cloudfront.net. To make it look a little nicer you can create a CNAME record that points to this for the domain entered when creating the distribution, in our example cloudfront.example.com.
Note that if the distribution is accessed through HTTPS you should not use a CNAME as this will create security warnings in the browser.
Using it in Rails
To start using the Cloufront distribution add it to production.rb as follows:
After you deploy this all requests for assets will be sent to Cloudfront, and Cloudfront directs the request to the location nearest the user. If a copy exists on this location Cloudfront will return it, if not it will forward the request to your server and store the asset returned.