Static Site Hosting with S3 and CloudFront

By Rich

Mon Mar 15 2021

I recentled needed to setup S3 and CloudFront to host a static website built with React. Below are the resources from the CloudFormation

CloudFormation

Hosting Bucket

The first step is to setup an S3 bucket to host the website.

HostingBucket:
  Type: AWS::S3::Bucket
  Properties:
    AccessControl: Private

CloudFront Certificate

To use a custom domain name with CloudFront you need to setup a certificate in Certificate Manager.

CloudFrontCertificate:
  Type: AWS::CertificateManager::Certificate
  Properties:
    DomainName: graphboss.com
    DomainValidationOptions:
      - DomainName: graphboss.com
        HostedZoneId: Z1OTIL07BUWDR5
      - DomainName: www.graphboss.com
        HostedZoneId: Z1OTIL07BUWDR5
    SubjectAlternativeNames:
      - www.graphboss.com
    ValidationMethod: DNS

CloudFront Origin Access Identity

To prevent people from acce

CloudFrontOAI:
  Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
  Properties:
    CloudFrontOriginAccessIdentityConfig:
      Comment: Allow access to the Graphboss S3 bucket from CloudFront

CloudFront Distribution

CloudFrontDistribution:
  Type: AWS::CloudFront::Distribution
  Properties:
    DistributionConfig:
      Comment: CDN for website
      Aliases:
        - graphboss.com
        - www.graphboss.com
      ViewerCertificate:
        AcmCertificateArn: !Ref CloudFrontCertificate
        SslSupportMethod: sni-only
      Enabled: true
      DefaultCacheBehavior:
        AllowedMethods:
          - GET
          - HEAD
          - OPTIONS
        ForwardedValues:
          QueryString: true
        TargetOriginId: HostingBucketOrigin
        ViewerProtocolPolicy: redirect-to-https
      DefaultRootObject: index.html
      CustomErrorResponses:
        - ErrorCode: 400
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 403
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 404
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 405
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 414
          ResponseCode: 200
          ResponsePagePath: /index.html
        - ErrorCode: 416
          ResponseCode: 200
          ResponsePagePath: /index.html
      Origins:
        - DomainName: !GetAtt HostingBucket.DomainName
          Id: HostingBucketOrigin
          S3OriginConfig:
            OriginAccessIdentity:
              Fn::Join:
                - "/"
                - - origin-access-identity/cloudfront
                  - !Ref CloudFrontOAI

Bucket Policy

Lastly you need to add a bucket policy that allows CloudFront to access the S3 bucket.

HostingBucketPolicy:
  Type: AWS::S3::BucketPolicy
  Properties:
    PolicyDocument:
      Id: PolicyForCloudFrontPrivateContent
      Version: 2012-10-17
      Statement:
        - Sid: PublicReadForGetBucketObjects
          Effect: Allow
          Principal:
            CanonicalUser: !GetAtt CloudFrontOAI.S3CanonicalUserId
          Action: "s3:GetObject"
          Resource: !Join
            - ""
            - - "arn:aws:s3:::"
              - !Ref HostingBucket
              - /*
    Bucket: !Ref HostingBucket

Want to learn more about serverless applications and devops with AWS?

Sign up for our newsletter.