A static website is simply html, css, js,… files hosted by AWS S3. They are cool because there are no servers for you to maintain and pay for. You only pay for the storage of your files and the amount of traffic your site gets. Security is greatly improved because your site has no servers or databases to hack into.
What AWS resources does this template use?
S3 (File storage & static website)
CloudFront (HTTPS & caching)
Certificate Manager (SSL Cert)
Route53 (DNS)
CodeBuild (Continuous deployment)
CodePipeline (Continuous deployment)
CodeCommit (GIT repo)
CloudFormation (Infrastructure as Code)
IAM (AWS permissions & users)
This seems like a lot just to host a static website! Yep, it is, that’s why I created this handy CloudFormation template so the next time I want to stand up a simple static website I just have to click the button above.
Once you’re logged into your account you need to create an IAM user with Programmatic access, and with AWSCodeCommitFullAccess & AdministratorAccess permissions. Also, your user will need CodeCommit (GIT) credentials. Don’t forget to download all of your credentials because you’ll need then later. See the screen shots below:
Step 3 - Purchase your domain name
Head on over to Route 53 and register your domain name. If you already have a domain name, don’t worry, you can point it at Route53 after you build the stack.
Step 4 - Build the stack
Click on the buttom at the top to build the stack. Use your domain name and app name as the input parameters.
You can also copy the cloudformation template and install the stack using the AWS command-line tools. Harder but recommended. You should really version control your IaC template as well as your code. Here are the commands to create, update, and delete the stack.
When AWS Certificate Manager creates your SSL certificate it sends and email to the domain name administrator (You). You have to get that email and click the confirmation link. Once this step has been completed the stack can continue being built. More information can be found here: http://docs.aws.amazon.com/acm/latest/userguide/gs-acm-validate.html
Once your stack has been built copy the output param which will be your CodeCommit repo URL.
What do I do after my stack has been created?
Use your CodeCommit repo and your CodeCommit credentials to start checking in your static site.
CodePipeline and CodeBuild are setup to continuously deploy your site as you push changes to your repo.
Branches and CodePipeline actions: master -> Pushes changes to APEX (yes ssl) develop -> Pushes changes to dev subdomain (no ssl)
What should the structure of my project be?
Great question. You need to add a buildspec.yml so CodeBuid knows how to build your project.
/www/assets/ -> Put all js, css, images, etc… in this folder. /www/index.html -> Put all html files in this folder. buildspec.yml -> CodeBuild uses this to build your project.
The mappings section allows you to add data to your template that you’ll need to lookup later… Like information based on availability zones. In our case we needed to lookup the S3 hosted zone ID given the availability zone we’re deploying to. Why doesn’t AWS make this info available by default? Good question, why not AWS?
Parameters are optional values that you can pass into your template. For use we passed in the domain name. This way we could use this template to setup many different static websites.
1
2
3
4
5
6
7
8
9
10
11
12
"Parameters": {
"ApexDomainName": {
"Description": "Domain name for your website (example.com)",
"Type": "String",
"Default": "example.com"
},
"AppName": {
"Description": "App name for your website (example). Only alphanumeric characters, dash, and underscore are supported.",
We need to create an SSL certificate to use with our apex domain. Pretty cool that AWS gives us a free SSL cert and cycles them for us when they expire. No more are they days of creating our own Certificate Request and sending it to GoDaddy.
We use a Content Delivery Network (CDN) for two reasons:
It caches our web assets, html, css, js, and image files at the edge
It handles our SSL certificate and termination
Our source is the apex S3 website. Besides the default behavior we added two additional behaviors for .js and .css files. For these files we want to use the query params within the cache key. I like to cache these files for a really long time. The only catch is that when you make changes to these files you have to add a version query param to the url when you request them in your html pages. Ex. /css/app.css?v=2. It is a good practice to just dynamically change this version every time you deploy.
The CodeBuild is the thing that actually uploads our website into S3. CodePipeline will hand CodeBuild all the files in the GIT repo and CodeBuild does its thing…
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
"CodeBuildRoot": {
"Type": "AWS::CodeBuild::Project",
"Properties": {
"Artifacts": {
"Type": "CODEPIPELINE"
},
"Environment": {
"ComputeType": "BUILD_GENERAL1_SMALL",
"Image": "aws/codebuild/ubuntu-base:14.04",
"Type": "LINUX_CONTAINER",
"EnvironmentVariables": [
{
"Name": "BUCKET_NAME",
"Value": {
"Ref": "RootBucket"
}
}
]
},
"Name": {
"Fn::Join": [
"_",
[
{
"Ref": "AppName"
},
"Root_Build"
]
]
},
"ServiceRole": {
"Ref": "CodeBuildRole"
},
"Source": {
"Type": "CODEPIPELINE"
},
"TimeoutInMinutes": 10
}
},
CodeBuild uses a buildspec.yml to perform the build. Here is our buildspec.yml This file has to be in the root of your project repo.