AWS Git-backed Static Website

with automatic updates on changes in CodeCommit Git repository

A number of CloudFormation templates have been published that generate AWS infrastructure to support a static website. I’ll toss another one into the ring with a feature I haven’t seen yet.

In this stack, changes to the CodeCommit Git repository automatically trigger an update to the content served by the static website. This automatic update is performed using CodePipeline and AWS Lambda.

This stack also includes features like HTTPS (with a free certificate), www redirect, email notification of Git updates, complete DNS support, web site access logs, infinite scaling, zero maintenance, and low cost.

One of the most exciting features is the launch-time ability to specify an AWS Lambda function plugin (ZIP file) that defines a static site generator to run on the Git repository site source before deploying to the static website. A sample plugin is provided for the popular Hugo static site generator.

Here is an architecture diagram outlining the various AWS services used in this stack. The arrows indicate the major direction of data flow. The heavy arrows indicate the flow of website content.

CloudFormation stack architecture diagram

Sure, this does look a bit complicated for something as simple as a static web site. But remember, this is all set up for you with a simple aws-cli command (or AWS Web Console button push) and there is nothing you need to maintain except the web site content in a Git repository. All of the AWS components are managed, scaled, replicated, protected, monitored, and repaired by Amazon.

The input to the CloudFormation stack includes:

  • Domain name for the static website

  • Email address to be notified of Git repository changes

The output of the CloudFormation stack includes:

  • DNS nameservers for you to set in your domain registrar

  • Git repository endpoint URL

Though I created this primarily as a proof of concept and demonstration of some nice CloudFormation and AWS service features, this stack is suitable for use in a production environment if its features match your requirements.

Speaking of which, no CloudFormation template meets everybody’s needs. For example, this one conveniently provides complete DNS nameservers for your domain. However, that also means that it assumes you only want a static website for your domain name and nothing else. If you need email or other services associated with the domain, you will need to modify the CloudFormation template, or use another approach.

How to run

To fire up an AWS Git-backed Static Website CloudFormation stack, you can click this button and fill out a couple input fields in the AWS console:

[![Launch CloudFormation stack][launchbutton]][launch] [launch]: https://console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/new?templateURL=https:%2F%2Fs3.amazonaws.com%2Frun.alestic.com%2Fcloudformation%2Faws-git-backed-static-website-cloudformation.yml&stackName=aws-git-backed-static-website [launchbutton]: https://s3.amazonaws.com/cloudformation-examples/cloudformation-launch-stack.png

I have provided copy+paste aws-cli commands in the GitHub repository. The GitHub repository provides all the source for this stack including the AWS Lambda function that syncs Git repository content to the website S3 bucket:

AWS Git-backed Static Website GitHub repository

If you have aws-cli set up, you might find it easier to use the provided commands than the AWS web console.

When the stack starts up, two email messages will be sent to the address associated with your domain’s registration and one will be sent to your AWS account address. Open each email and approve these:

  • ACM Certificate (2)
  • SNS topic subscription

The CloudFormation stack will be stuck until the ACM certificates are approved. The CloudFront distributions are created afterwards and can take over 30 minutes to complete.

Once the stack completes, get the nameservers for the Route 53 hosted zone, and set these in your domain’s registrar. Get the CodeCommit endpoint URL and use this to clone the Git repository. There are convenient aws-cli commands to perform these fuctions in the project’s GitHub repository linked to above.

AWS Services

The stack uses a number of AWS services including:

  • CloudFormation - Infrastructure management.

  • CodeCommit - Git repository.

  • CodePipeline - Passes Git repository content to AWS Lambda when modified.

  • AWS Lambda - Syncs Git repository content to S3 bucket for website

  • S3 buckets - Website content, www redirect, access logs, CodePipeline artifacts

  • CloudFront - CDN, HTTPS management

  • Certificate Manager - Creation of free certificate for HTTPS

  • CloudWatch - AWS Lambda log output, metrics

  • SNS - Git repository activity notification

  • Route 53 - DNS for website

  • IAM - Manage resource security and permissions

Cost

As far as I can tell, this CloudFormation stack currently costs around $0.51 per month in a new AWS account with nothing else running a reasonable amount of storage for the web site content, and up to 5 Git users. This minimal cost is due to there being no free tier for Route 53 at the moment.

If you have too many GB of content, too many tens of thousands of requests, etc., you may start to see additional pennies being added to your costs.

If you stop and start the stack, it will cost an additional $1 each time because of the odd CodePipeline pricing structure. See the AWS pricing guides for complete details, and monitor your account spending closely.

Notes

  • This CloudFormation stack will only work in regions that have all of the required services and features available. The only one I’m sure about is ue-east-1. Let me know if you get it to work elsewhere.

  • This CloudFormation stack uses an AWS Lambda function that is installed from the run.alestic.com S3 bucket provided by Eric Hammond. You are welcome to use the provided script to build your own AWS Lambda function ZIP file, upload it to S3, and specify the location in the launch parameters.

  • Git changes are not reflected immediately on the website. It takes a minute for CodeDeploy to notice the change; a minute to get the latest Git branch content, ZIP, upload to S3; and a minute for the AWS Lambda function to download, unzip, and sync the content to the S3 bucket. Then the CloudFront CDN TTL may prevent the changes from being seen for another minute. Or so.

Thanks

Thanks to Mitch Garnaat for pointing me in the right direction for getting the aws-cli into an AWS Lambda function. This was important because “aws s3 sync” is much smarter than the other currently availble options for syncing website content with S3.

Thanks to AWS Community Hero Onur Salk for pointing me in the direction of CloudPipeline for triggering AWS Lamda functions off of CodeCommit changes.

Thanks to Ryan Brown for already submitting a pull request with lots of nice cleanup of the CloudFormation template, teaching me a few things in the process.

Some other resources you might fine useful:

[Creating a Static Website Using a Custom Domain - Amazon Web Services][awslink] [awslink]: http://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/quickref-s3.html#scenario-s3-bucket-website-customdomain

[S3 Static Website with CloudFront and Route 53 - AWS Sysadmin][sysadminlink] [sysadminlink]: http://awssystemadministration.com/s3-static-website-with-cloudfront-and-route-53/

[Continuous Delivery with AWS CodePipeline - Onur Salk][onurlink] [onurlink]: http://www.awsomeblog.com/continuous-delivery-aws-codepipeline/

[Automate CodeCommit and CodePipeline in AWS CloudFormation - Stelligent][stelligentlink1] [stelligentlink1]: https://stelligent.com/2016/04/25/automate-codecommit-and-codepipeline-in-aws-cloudformation/

[Running AWS Lambda Functions in AWS CodePipeline using CloudFormation - Stelligent][stelligentlink2] [stelligentlink2]: https://stelligent.com/2016/02/08/aws-lambda-functions-aws-codepipeline-cloudformation/

You are welcome to use, copy, and fork this repository. I would recommend contacting me before spending time on pull requests, as I have specific limited goals for this stack and don’t plan to extend its features much more.

[Update 2016-10-28: Added Notes section.]

[Update 2016-11-01: Added note about static site generation and Hugo plugin.]