CloudFormation And Static Sites

Host A Global Static A Site In Just A Couple Clicks

Posted by Ryan S. Brown on Sun, Oct 16, 2016
In Mini-Project
Tags: cloudformation, cloudfront

Listening to the Engineers & Coffee podcast the other day, Donnie mentioned the joys of the new CloudFormation changes. Being someone who’s worked on two different YAML-driven orchestration/config management tools (Heat and Ansible) I don’t need to be sold on YAML.

The Bad Old Days

Before YAML support, I’ve been using little scripts like this to use YAML for CloudFormation templates.

python -c 'import sys,yaml,json; json.dump(yaml.load(sys.stdin), sys.stdout)' \
    < template.yaml \
    > template.json

In any pipeline that needed CloudFormation, it’s easy to fine a spot that will run the transformation. The Ansible’s CloudFormation module even had YAML-to-JSON translation built in as template_yaml.

So why go to all the trouble to write templates in YAML, it’s just a different way to specify the same stuff right? There’s a lot to be said for making templates easier to read later.

The New Hotness

As part of a fall cleanup of my AWS account, I rebuilt all my static sites with new CloudFormation templates to support HTTP/2, IPv6, and use the new support for Amazon Certificate Manager. Previously, I built my own Lambda custom resource to provide ACM certs to my sites.

SSLCert:
  # Replace Lambda custom resource with official CloudFormation
  Type: "AWS::CertificateManager::Certificate"
  Properties:
    DomainName: !Ref SiteDomain
    DomainValidationOptions:
      - DomainName: !Ref SiteDomain
        ValidationDomain: !Ref DomainRoot

All that amounted a full rewrite, and I was able to take advantage of the new syntax for intrinsic functions. !Ref MyVar is so much cleaner than {"Ref": "MyVar"}.

The full template is available on Github as part of my personal blog repo and it’s ready to use as long as you have:

  1. an AWS account
  2. Route53 for domain hosting
  3. static content to put in the S3 bucket

It’s especially nice to be able to use comments to explain different bits of the template, like what the Magic CloudFront Hosted Zone is:

- Name: !Ref SiteDomain
  Type: A
  AliasTarget:
    DNSName: !GetAtt CDN.DomainName
    # magic cloudfront hosted zone id
    # see http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-route53-aliastarget.html
    HostedZoneId: Z2FDTNDATAQYW2

The new !Ref and !GetAttr clean up the references to the CloudFront CDN, and with a comment I can see where that alias target came from. Same thing later in a mapping function to map regions to S3 website endpoints.

Mappings:
  RegionMap:
    # This is a map of the S3 website endpoints as of Jan 7 2016
    # http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region
    # Don't edit this
    sa-east-1:
      websiteendpoint: "s3-website-sa-east-1.amazonaws.com"
      ZoneId: "Z31GFT0UA1I2HV"
    ap-northeast-1:
      websiteendpoint: "s3-website-ap-northeast-1.amazonaws.com"
      ZoneId: "Z2M4EHUR26P7ZW"

This template probably looks about like the one the Engineers & Coffee hosts had to write for their own site, minus the Lambda/API Gateway backend. Check it out, and remember to take advantage of comments and new cleaner syntax with the CloudFormation YAML templates.

Make Your Own

My site, rsb.io is on this template now and if you have improvements to the template pull requests are welcome. As always, the stack is launchable in one click:

Launch stack MyStaticSite

If you like this sort of thing, subscribe to the Serverless Code mailing list or send questions them to ryan@serverlesscode.com or @ryan_sb on Twitter.


Tweet this, send to Hackernews, or post on Reddit