Automate Building a Unique Domain Hosting Environment with AWS CloudFormation
Tags: aws, cloudformation, route53
Published: 2022-02-28 12:05:21

![img](https://day-journal.com/memo/images/try-084_00.png)

### I automated building a unique domain hosting environment with AWS CloudFormation :tada:  

<br>

In my previous article, "[Build a Unique Domain Hosting Environment with Amazon Route 53, AWS WAF, Amazon CloudFront, and Amazon S3](https://dev.to/aws-builders/build-a-unique-domain-hosting-environment-with-amazon-route-53-aws-waf-amazon-cloudfront-and-amazon-s3-5eip)," I tried to implement the contents of that article with AWS CloudFormation.

<br>

I've made the template available on GitHub, so please use it!

[aws-cloudformation-templates-showcase](https://github.com/dayjournal/aws-cloudformation-templates-showcase)

#### certificate-create.yml

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Certificate creation
Parameters:
  DomainName:
    Description: Domain Name
    Type: String
  HostedZoneId:
    Description: Host Zone ID
    Type: String
Resources:
  CertificateManagerCertificate:
    Type: AWS::CertificateManager::Certificate
    Properties:
      DomainName: !Sub ${DomainName}
      DomainValidationOptions:
        -
          DomainName: !Sub ${DomainName}
          HostedZoneId: !Sub ${HostedZoneId}
      ValidationMethod: DNS
```

#### hosting.yml

```yaml
AWSTemplateFormatVersion: 2010-09-09
Description: Build a Unique Domain Hosting Environment with Amazon Route 53, Amazon CloudFront, and Amazon S3
Parameters:
  DomainName:
    Description: Domain Name
    Type: String
  HostedZoneId:
    Description: Host Zone ID
    Type: String
  CertificateId:
    Description: Certificate ID
    Type: String
Resources:
  S3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub ${AWS::StackName}-${AWS::Region}-${AWS::AccountId}
  S3BucketPolicy:
    Type: AWS::S3::BucketPolicy
    DependsOn:
      - CloudFrontOriginAccessIdentity
    Properties:
      Bucket: !Sub ${S3Bucket}
      PolicyDocument:
        Statement:
          -
            Sid: PolicyForCloudFrontPrivateContent
            Effect: Allow
            Principal:
              AWS: !Sub arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity ${CloudFrontOriginAccessIdentity}
            Action: s3:GetObject
            Resource: !Sub arn:aws:s3:::${S3Bucket}/*
  CloudFrontOriginAccessIdentity:
    Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
    Properties:
      CloudFrontOriginAccessIdentityConfig:
        Comment: Unique Domain Hosting Environment
  CloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    DependsOn:
      - S3Bucket
      - CloudFrontOriginAccessIdentity
    Properties:
      DistributionConfig:
        Aliases:
          - !Sub ${DomainName}
        Origins:
          -
            DomainName: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
            Id: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
            S3OriginConfig:
              OriginAccessIdentity: !Sub origin-access-identity/cloudfront/${CloudFrontOriginAccessIdentity}
        DefaultCacheBehavior:
          TargetOriginId: !Sub ${S3Bucket}.s3.${AWS::Region}.amazonaws.com
          Compress: true
          AllowedMethods:
            - HEAD
            - GET
          CachedMethods:
            - HEAD
            - GET
          ViewerProtocolPolicy: redirect-to-https
          CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
        CustomErrorResponses:
          -
            ErrorCode: 403
            ResponsePagePath: /index.html
            ResponseCode: 200
            ErrorCachingMinTTL: 0
          -
            ErrorCode: 404
            ResponsePagePath: /index.html
            ResponseCode: 200
            ErrorCachingMinTTL: 0
        PriceClass: PriceClass_All
        Enabled: true
        ViewerCertificate:
          AcmCertificateArn: !Sub arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/${CertificateId}
          MinimumProtocolVersion: TLSv1.2_2021
          SslSupportMethod: sni-only
        Restrictions:
          GeoRestriction:
            RestrictionType: none
        HttpVersion: http2
        DefaultRootObject: index.html
        IPV6Enabled: true
  Route53RecordSet:
    Type: AWS::Route53::RecordSet
    DependsOn:
      - CloudFrontDistribution
    Properties:
      Name: !Sub ${DomainName}
      HostedZoneId: !Sub ${HostedZoneId}
      Type: A
      AliasTarget:
        DNSName: !GetAtt CloudFrontDistribution.DomainName
        HostedZoneId: Z2FDTNDATAQYW2
```

<br>

## Advance Preparation

Get a unique domain using Amazon Route 53
Make a note of the target domain name and host zone ID 

![img](https://day-journal.com/memo/images/try-084_01.png)

<br>

## How to build

1. Auto-deploy SSL certificate in the specified region
2. Auto-deploy unique domain hosting environment in any region

<br>

## Auto-Deploy SSL Certificate in the Specified Region

First, we will auto-deploy an SSL certificate in the specified region. We need to create in the "us-east-1" region to use the SSL certificate with CloudFront. 

Access CloudFormation with the region "us-east-1," and click "Stack" → “Create Stack” → "Use New Resource."
![img](https://day-journal.com/memo/images/try-084_02.png)

Select "Template ready" as a prerequisite. To specify the template, select "Upload template file" and upload the file → Click "Next." Use the CloudFormation template "certificate-create.yml."
![img](https://day-journal.com/memo/images/try-084_03.png)

Set the desired stack name, domain name, and host zone ID → Click "Next."
![img](https://day-journal.com/memo/images/try-084_04.png)

Set the stack options as default → Click "Next."
![img](https://day-journal.com/memo/images/try-084_05.png)

Confirm the settings → Click "Create Stack."
![img](https://day-journal.com/memo/images/try-084_06.png)

Confirm that the stack has been created.
![img](https://day-journal.com/memo/images/try-084_07.png)

Check the AWS Certificate Manager for the "us-east-1" region, and you will see that the SSL certificate has been created automatically. Note down the target "Certificate ID" for use in the next template.
![img](https://day-journal.com/memo/images/try-084_08.png)

<br>

## Auto-Deploy Unique Domain Hosting Environment in Any Region

Finally, we will auto-deploy a unique domain hosting environment in any region.

Access CloudFormation in the region you want to deploy to. Click “Stack” → “Create Stack” → "Use New Resource."
![img](https://day-journal.com/memo/images/try-084_09.png)

For prerequisites, select "Template is ready." To specify the template, select "Upload template file" and upload the file → Click "Next." Use "hosting.yml" as the CloudFormation template.
![img](https://day-journal.com/memo/images/try-084_10.png)

Set the desired stack name, certificate ID, domain name, and host zone ID → Click "Next."
![img](https://day-journal.com/memo/images/try-084_11.png)

Set the stack options as default this time → Click "Next."
![img](https://day-journal.com/memo/images/try-084_12.png)

Confirm the settings → Click "Create Stack."
![img](https://day-journal.com/memo/images/try-084_13.png)

Confirm that the stack has been created.
![img](https://day-journal.com/memo/images/try-084_14.png)

Confirm that it has been automatically deployed to Amazon CloudFront.
![img](https://day-journal.com/memo/images/try-084_15.png)

Confirm that it has been automatically deployed to Amazon S3.
![img](https://day-journal.com/memo/images/try-084_16.png)

Upload the set of files you want to publish to the deployed S3 bucket.
![img](https://day-journal.com/memo/images/try-084_17.png)

When you access a unique domain, you will see the uploaded WebSite.
![img](https://day-journal.com/memo/images/try-084_18.png)

<br>

Using AWS CloudFormation, it is possible to automate the build of various resources such as unique domain hosting :bulb: 

In the future, I'd like to experiment with AWS CDK, etc. to see how far each service configuration can be defined.

<br>

Related Articles

{% link https://dev.to/aws-builders/automate-building-a-unique-domain-hosting-environment-with-aws-cdk-1dd1 %}
{% link https://dev.to/aws-builders/build-a-unique-domain-hosting-environment-with-aws-amplify-3jl0 %}
{% link https://dev.to/aws-builders/build-a-unique-domain-hosting-environment-with-amazon-route-53-aws-waf-amazon-cloudfront-and-amazon-s3-5eip %}