---
title: Using Amazon Cloudfront with Drupal
description: CDN's are nothing new, and Metal Toad has projects running on competing systems including Akamai and Level 3.
---

[Blog ](https://www.metaltoad.com/blog)

# [Using Amazon Cloudfront with Drupal](https://www.metaltoad.com/blog/amazon-cloudfront-drupal)

 Written by [Metal Toad Staff](https://www.metaltoad.com/blog/author/metal-toad-staff) | Sep 12, 2012 12:00:00 AM

We like to use our own site to experiment with different technologies. CDN's are nothing new, and Metal Toad has projects running on competing systems including Akamai and Level 3. Still, I think Amazon Cloudfront is an interesting offering and I wanted to give it a spin. Here's my review of the service after setting it up with Drupal:

### Pros:

- Easy setup, low-cost, only pay for what you use
- Support for CNAMES and domain sharding (e.g. static[1234].metaltoad.com)
- Supports `Accept:Byte-Range` headers (important for media files)
- Supports gzip compression (assuming your origin server does the compression)
- Supports HTTPS
- Honors cache-control headers
- Custom HTTP headers are passed through to edge requests (including CORS)

### Cons:

- No global or directory "purge" command - each file must be invalidated individually
- No custom SSL Certificates, so you can't use CNAMES with HTTPS
- Fussy about SSL ciphers on the origin server (Cloudfront wasn't compatible with the ciphers configured on our load balancer, so I had to use "http-only" instead of "match-viewer")
- Only minimal logging, no reports or graphs

### Domain sharding

Multiple CNAMES add a little overhead with extra DNS lookups, but increase the number of parallel downloads (browsers impose a [per-hostname limit](http://www.browserscope.org/?category=network)). To minimize upstream bandwidth needed, these domains should be cookie-free. Since I chose subdomains of the site itself, I needed to adjust some cookie settings in Drupal:

- In settings.php, set `$cookie_domain = 'www.metaltoad.com';`
- In the Google Analytics module, set the tracking to "One domain with multiple subdomains"

Thanks to some new alter hooks in Drupal 7, all you need to implement a static file CDN is `hook_file_url_alter()`. There's an [actively maintained CDN module](http://drupal.org/project/cdn), but in the spirit of inquiry I decided to implement the hook directly.

### Module file

```
/**
 * Implements hook_file_url_alter().
 */
function mymodule_file_url_alter(&$uri) {
  // Route static files to Amazon CloudFront.
  if ($_SERVER['HTTP_HOST'] == 'www.metaltoad.com') {
    if ($GLOBALS['is_https']) {
      // Cloudfront doesn't support custom SSL certs, so we need to use Amazon's.
      $cdn = 'https://abcdef12345.cloudfront.net';
    }
    else {
      // Multiple hostnames to parallelize downloads.
      $shard = crc32($uri) % 4 + 1;
      $cdn = "http://static$shard.metaltoad.com";
    }
    $scheme = file_uri_scheme($uri);
    if ($scheme == 'public') {
      $wrapper = file_stream_wrapper_get_instance_by_scheme('public');
      $path = $wrapper->getDirectoryPath() . '/' . file_uri_target($uri);
      $uri = "$cdn/$path";
    }
    else if (!$scheme && strpos($uri, '//') !== 0) {
      $uri = "$cdn/$uri";
    }
  }
}
 
/**
 * Implements hook_boot().
 */
function mymodule_boot() {
  // Make sure Amazon CloudFront doesn't serve dynamic content.
  if (!empty($_SERVER['HTTP_X_AMZ_CF_ID']) && !strstr($_GET['q'], 'files/styles')) {
    header("HTTP/1.0 404 Not Found");
    print '404 Not Found';
    exit();
  }
}
 
/**
 * Implements hook_css_alter().
 */
function mymodule_css_alter(&$css) {
  // Mangle the paths slightly so that drupal_build_css_cache() will generate
  // different keys on HTTPS.  Necessary because CDN URL varies by protocol.
  if ($GLOBALS['is_https']) {
    foreach ($css as $key => $style) {
      if ($style['preprocess'] && $style['type'] == 'file') {
        $css[$key]['data'] = './' . $style['data'];
      }
    }
  }
}
```

### .htaccess

```
# Set CORS header on static assets for CDN.
<FilesMatch "\.(ttf|otf|eot|woff|css|css\.gz|js|js\.gz)$">
  <IfModule mod_headers.c>
    Header set Access-Control-Allow-Origin "*"
  </IfModule>
</FilesMatch>
```

The HTTPS and sharding support adds a little complexity, but overall the integration is straightforward. I'd recommend Cloudfront to anyone who wants an easy and cost-effective scalability win.

[View full post](https://www.metaltoad.com/blog/amazon-cloudfront-drupal)

```json
{
  "@context" : "http://schema.org",
  "@type" : "BlogPosting",
  "author" : {
    "@type" : "Person",
    "name" : "Metal Toad Staff"
  },
  "dateModified" : "2025-05-20T17:05:12.428Z",
  "datePublished" : "2012-09-12T00:00:00Z",
  "headline" : "Using Amazon Cloudfront with Drupal",
  "image" : {
    "@type" : "ImageObject",
    "height" : 500,
    "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/Imported_Blog_Media/Metal_Toad_blog_generic-Aug-11-2023-10-21-18-3127-PM.jpg",
    "width" : 870
  },
  "mainEntityOfPage" : "https://www.metaltoad.com/blog/amazon-cloudfront-drupal",
  "publisher" : {
    "@type" : "Organization",
    "logo" : {
      "@type" : "ImageObject",
      "height" : 60.0,
      "url" : "https://6104926.fs1.hubspotusercontent-na1.net/hubfs/6104926/social-suggested-images/6104926.fs1.hubspotusercontent-na1.nethub6104926hubfsMetal_Toad_Logo_orange_horizontal-50-1.jpg",
      "width" : 240.00002
    },
    "name" : "Blog"
  }
}
```