Back to top

Create your own website

Infrastructure automation for hosting your website

Purpose

You might have seen many examples of screen by screen walk-through about creating a website. This blog will help you to create a scalable website. Not just that, This blueprint can help you create a website with just a single execution and can be reproduced many times. We will use cloudformation which helps you write infrastructure as code. I assume you have some familiarity with AWS services used in this blog and basic concepts about websites and you have an AWS account to try

You need some HTML code

I used react-helloworld example from here. Follow the instructutions in README.md

git clone https://github.com/ahfarmer/calculator.git
npm install
npm run-script build

AWS Resources

You will be creating an S3 bucket to keep your code, a CloudFront distribution.

CloudFront Access Identity

We need to restrict the access to your site using an origin access identity so that only cloudfront distribution can access your bucket.

  CDNS3AccessId:
    Type: 'AWS::CloudFront::CloudFrontOriginAccessIdentity'
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: 'This Distribution of calculator app'

S3 Bucket

Amazon Simple Storage Service Amazon S3 is one of many storage services offered by Amazon. You can store your data in Object format and protect it. It is fast, secure, durable, scalable and reliable and the metrics differ slightly based on the type of storage class.

So, Let’s look at how to create an S3 bucket using for our usecase using Cloudformation

  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Ref BucketName
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: AES256
      Tags:
        -
          Key: type
          Value: website

Now, we need to add some policies so that cloudfront can access your S3 Bucket.

  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref S3Bucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: CloudFrontAccess
            Effect: 'Allow'
            Action: 
              - s3:GetObject
              - s3:ListBucket
            Principal:
              AWS:
                !Sub 'arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CDNS3AccessId}'
            Resource: 
              - !Sub '${S3Bucket.Arn}/*'
              - !Sub '${S3Bucket.Arn}'

CloudFront

[AWS Cloudfront] (https://aws.amazon.com/cloudfront/) is a content delivery network like Akamai or Cloudfare. It servers your content securely through it’s globally distributed high speed edge networks. A distribution tells how and where to manage and serve the content from.

lets see how to create a Cloudfront a distribution

  CloudFrontDistribution:
    Type: 'AWS::CloudFront::Distribution'
    Properties:
      DistributionConfig:
        DefaultRootObject: !Ref DefaultRootObject
        Enabled: true
        HttpVersion: http2
        PriceClass: PriceClass_100

Origins

When you create a distribution, you need to specify what is the source of your content. As you know, We have a bucket created for it and we are going to upload our website files there. So, We need to create an Origin for the S3Bucket. Here is how

        Origins:
          - DomainName: !Sub '${S3Bucket}.s3.amazonaws.com'
            Id: s3origin
            S3OriginConfig:
              OriginAccessIdentity: !Sub 'origin-access-identity/cloudfront/${CDNS3AccessId}'

behaviors

You will need to define some request and response behaviors on how cloudfront process your request and response to and from the S3 bucket. The behavior configures information like caching which one one of many features of cloudfront, cookies, Cross origin resource sharing(CORS) etc. Since we have only one bucket, It will be a default behavior.

        DefaultCacheBehavior:
          TargetOriginId: 's3origin'
          DefaultTTL: 300 #if you want to avoid frequently fetching from S3, keep max
          MaxTTL: 280000
          MinTTL: 0
          ForwardedValues:
            QueryString: false
            Cookies:
              Forward: none
          ViewerProtocolPolicy: redirect-to-https
          Compress: true

Error Response

Defining error response let you define the custom error messages to the user. for ex, user is trying an invalid URL and the origin returns 404 and cloudfront will return the custom error message to the user as defined in the error response.

When you host a static site, It is important to define the error response for 404 user to index.html for routing to work correctly with single page applications using react. You can [refer](### References & Further Readings) for different options for web applications with directory structures

        CustomErrorResponses:
        - ErrorCode: 403 # Access denied
          ResponseCode: 200
          ResponsePagePath: '/login.html'
        - ErrorCode: 404 # not found
          ResponseCode: 404
          ResponsePagePath: '/index.html'

Finally!

Now you have the cloudformation ready, You can run it using aws-cli or upload to s3 bucket and run from cloudformation console.

Once you execute you will be able to view your bucket. Now copy the content of public folder in your localmachine to S3 bucket.

Voila! You will be able to access your website using the cloudfront distribution URL.

References & Further Readings