Amazon CloudFront: Configuring a CDN in under 5 minutes

I was very thrilled to hear about the public release of Amazon’s much awaited CDN service dubbed CloudFront. It took me 5 minutes to configure and start using it to serve static content off it (I used S3 for static content until now, so the transition was easy).

  1. Prepare an .aws-secrets file to store your AWS access identifiers and get the cfcurl.pl script (tutorial).
  2. Define a Distribution. Save this snippet in a file called create_request.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <DistributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2008-06-30/">
    ..<Origin>YourBucketNameHere.s3.amazonaws.com</Origin>
    ..<CallerReference>20080930090000</CallerReference>
    ..<CNAME>cdn.example.com</CNAME>
    ..<Enabled>true</Enabled>
    </DistributionConfig>
  3. Run the following command:
    ./cfcurl.pl --keyname <key name from .aws-secrets file> -- -X POST -i -H "Content-Type:text/xml; charset=UTF-8" --upload-file create_request.xml https://cloudfront.amazonaws.com/2008-06-30/distribution
  4. Save the response (especially the E-Tag) for later, you may need it to update the configuration.
  5. Create a CNAME entry in your DNS server using the DomainName in the response.
  6. Done!

I’m trying to think about an elegant way to manage versioning from now on (in PHP). I used to add a query-string version parameter to each resource to deal with client-side caching. With CloudFront, I need actual filenames to change, since Amazon’s servers ignore the query-string parameters when fetching the file from the S3 origin. Any ideas would be greatly appreciated!

Update: see comment below.

Tags: , , , , ,

  • Mickey

    Hi there,

    IMHO (make sure to ask many more people, maybe there are better or simpler solutions) you will have to add to your deployment process a script (whether it’s shell script, PHP, PERL, or whatever) that does 2 things:

    1. Iterates all over your static files (images, css, JavaScript, swf etc…) and renames them. For example, if you have a directory called “Images” with 2 files:

    image1.jpg
    image2.jpg

    The script will have to modify the file names to something containing the unique new tag, (or version, or release, or whatever you call it):

    image1-3.1.1_200801122.jpg
    image1-3.1.1_200801122.jpg

    2. The script will also have to go over all your PHP/HTML/JavaScript etc… and change wherever you reference such a file to now hold those new file names, for example:

    If example.html has the following line:

    it will need to be changed to

    If example.php has the following line:

    unlink(“image2.jpg”);

    it will need to be changed to
    unlink(“image1-3.1.1_200801122.jpg”);

    If you are lucky enough you probably have a good chance to find such open source script somewhere, where you only have to define some variables or constants like, what directories to search for static content, in what directories your PHP scripts live, what is the new unique tag (or version, or release, or whatever you call it) etc…

    Let me know if you find such a script, I’m sure I could use it some day :-)

    Good luck!

  • http://www.innerlogics.com nivs

    Thanks Mickey!

    I finally finished my “resources compiler” script and I used some of the ideas you wrote about in your comment.
    What my script does is to go over all static resources and upload them to S3, renamed to contain their version number.

    The script stores the MD5 hash of each resource and compares it to a previous value to detect changes. Naturally, only modified resources are uploaded.

    During each run, the script goes over a list of resources to compile. These may be images, or flash files – which are uploaded directly, or CSS and JS files, which are combined and minified before upload.
    CSS files are also scanned for resource file references, which are automatically changed to the versioned file names.

    Since I’m using the Smarty template engine, I did not need the script to go over all my source files. I simply added a custom Smarty modifier I called “resource”, which looks up and returns the versioned URL of the requested resource. As a bonus, it can also return the dimensions of image resources.

    Two notes about CloudFront that could help others – I’ve spent a lot of time banging my head over this.
    1. If you want to gzip your files, you must upload a gzipped version – CloudFront or S3 don’t do it for you. You should also manually perform browser detection and fetch a non-gzipped version when necessary.
    2. Content Headers are critical for uploaded files. Content-Type is a must, and expiration headers (Expires, Cache-Control and Last-Modified) are required to avoid unnecessary hits and for the best user experience.

    I’m still not sure I used the best possible combination of headers for static files.

  • http://www.cloudberrylab.com/ Andy

    Great post. if you want to use the tool to configure CloudFront service you may want to check out the latest version of CloudBerry Explorer for Amazon S3. http://www.cloudberrylab.com/