Update: Amazon has added support for CORS, though there are some issues with wildcard support. However, most people will be able to set the header in S3 normally and serve fonts from S3 without issue!

This will be brisk, but I intend to cover all of the caveats involved in distributing webfonts via AWS's CloudFront CDN.

As browser support for @font-face CSS directives has improved to the point where they are now well supported, browsers have also been converging on a single font format to support. In addition to that, although there were lots of headaches, a solid syntax for webfonts has also been developed. Unfortunately, to maximize the number of users who see your fonts, you will need at least 3, probably 4, different font formats:

  • woff for IE9+, FF, Chrome (technically, eot+ttf cover these browsers)
  • ttf/otf for Safari & Opera
  • svg for older iOS & Android devices
  • eot for IE8 and older

There are solid services for webfonts, but if you want to serve your own off CloudFront, there's a big problem. FireFox and IE9+ implement HTTP access control, designed to restrict the type of content which can be successfully hotlinked off of other sites. From the foundry point of view, they don't want to sell access to a webfont to one site and have it show up everywhere else for free; from a customers point of view, they don't want to pay for delivery of licensed content to other domains.

The way to authorize cross-domain font access is via the HTTP Header Access-Control-Allow-Origin, which can be set to a domain or to * to match all domains. The big snag for serving webfonts off of CloudFront is that S3 and CloudFront do not support this header. A request was made to AWS in June 2009, and nearly 3 years later no action's been taken.

This blog post wouldn't exist if there wasn't a way around this, though. CloudFront, while integrating quite nicely with S3, can also be used to front a regular HTTP resource, called a "Custom Origin" in CloudFront's help literature. When you hit your CloudFront URL, it will proxy that request to the Origin you give it, and then cache it to be served locally until it times out (which you also have control over via Expires headers).

This means you can start up a t1.micro EC2 instance with a simple HTTP server serving your font files and CSS, and front that with CloudFront rather than an S3 bucket. A simple nginx config like this would work:

server {
    listen 80;
    access_log /var/log/nginx/static.log
    autoindex on;

    location / {
        root /var/www/static/;
        add_header Access-Control-Allow-Origin example.com;

After this is set up, create a CloudFront distribution with the DNS name of your EC2 t1.micro, wait for it to become "Deployed", and hit a font endpoint that you have set up on your EC2 box. CloudFront will be faithful to the headers you've set; once you are starting to get cache hits on CloudFront, you can inspect the headers and see something like:

HTTP/1.0 200 OK
Server: nginx/0.7.65
Date: Wed, 15 Feb 2012 22:14:45 GMT
Content-Type: font/woff
Content-Length: 281981
Last-Modified: Wed, 15 Feb 2012 21:56:25 GMT
Access-Control-Allow-Origin: example.com
Accept-Ranges: bytes
Age: 2570
X-Cache: Hit from cloudfront

With the ACAO header, new bulletproof CSS syntax, and font formats described above, your fonts will serve from the AWS CDN and work in nearly every browser that supports webfonts including old versions of IE and mobile devices!

Feb 15 2012