Hosting a Static Website in S3

The below is still a work in progress and may not be complete.
The below is bits and pieces cobbled together to start hosting a static website in AWS.

During this process, we have used the listed AWS Services: CloudFront, CodeBuild, CodePipeline, IAM, S3, CodeStar Connections; and GitHub as our Repository Provider.

Notes are brief, and are not step-by-step instructions as such right now. You will need to infer some items from the below.

This Solution should be well below $5 per month as most of the items are within the Always Free Tier except the AWS S3 Storage (Which only has valid free-tier for the first 12 month)..

Setup the AWS Components

Setup S3

You will need to create two AWS S3 Buckets. One for Artifacts, and One for the Website itself.

  • Create the bucket for your Pipeline Files. Ensure that Block all public access is checked. It's recommended you also enable Server-side encryption by default with SSE-S3.

  • Create a bucket for your Website Files. Ensure that block all public access is NOT checked. This bucket will be open to the workd as it will need to be configured to host a website.

  • When the bucket is created. Go to Properties tab and Edit Static website hosting. Set it to Enable, and select the type as Host a static website. Save Changes. Note the URL under Bucket website endpoint.

  • Go to Permissions tab and Edit the Bucket policy. Paste in a policy such as the below sample. Update ${website-bucket-name} accordingly.

 2    "Version": "2012-10-17",
 3    "Statement": [
 4        {
 5            "Sid": "",
 6            "Effect": "Allow",
 7            "Principal": {
 8                "AWS": "*"
 9            },
10            "Action": "s3:GetObject",
11            "Resource": "arn:aws:s3:::${website-bucket-name}/*"
12        }
13    ]

Setup IAM

You will need to first create an IAM Role which your CodePipeline and CodeBuild will be able to assume. Some of the below permissions can be drilled down further, as they are fairly generic.

  • Create a Role called codepipeline in IAM.
  • Create a Policy called codepipeline-access. Paste in a policy such as the below sample. Update ${website-bucket-name} and ${pipeline-bucket-name} accordingly. Attach the policy to the role you created in the step prior.
 2    "Version": "2012-10-17",
 3    "Statement": [
 4        {
 5            "Sid": "",
 6            "Effect": "Allow",
 7            "Action": "s3:*",
 8            "Resource": [
 9                "arn:aws:s3:::${pipeline-bucket-name}/*",
10                "arn:aws:s3:::${pipeline-bucket-name}",
11                "arn:aws:s3:::${website-bucket-name}/*",
12                "arn:aws:s3:::${website-bucket-name}"
13            ]
14        },
15        {
16            "Sid": "",
17            "Effect": "Allow",
18            "Action": [
19                "codestar-connections:*",
20                "codebuild:*",
21                "cloudfront:CreateInvalidation"
22            ],
23            "Resource": "*"
24        },
25        {
26            "Sid": "",
27            "Effect": "Allow",
28            "Action": [
29                "logs:Put*",
30                "logs:FilterLogEvents",
31                "logs:Create*"
32            ],
33            "Resource": "*"
34        }
35    ]

Setup CloudFront

  • Access Cloudfront and select Create distribution.
  • Under Origin domain - enter the Bucket website endpoint you noted above. Select HTTP only.
  • Under Name - Enter a name relating to your website.
  • Under Viewer protocol policy, set your desired actions. If you have a proper SSL you can set it up later and use Redirect HTTP to HTTPS.
  • Under Allowed HTTP methods, select GET, HEAD.
  • You can setup Alternate dmain name here, but make sure you have an ACM Certificate to cover it, and setup Customer SSL certificate if you wish to use HTTPS.
  • Leave everything else as default for the moment and click Create distribution.
  • Note down the Distribution ID, as you will need it for the Pipeline.

Setup the Pipeline

Now that all the components have been created, let's setup the Pipeline to Tie them all Together.

Setup CodeBuild

Add a buildSpec.yml file to the GitHub Repo in order to automatically upload your files to AWS S3, and Invalidate the Cloudfront Cache.

1version: 0.2
4  install:
5    commands:
6      - aws s3 sync ./public/ s3://$BUCKETNAME/
7      - aws cloudfront create-invalidation --distribution-id $CLOUDFRONT_ID --paths "/*"