How to deploy a static website on a PRIVATE S3 bucket served by CloudFront on a custom domain name.
Tags: aws, s3, cloudfront, route53
Published: 2023-01-21 10:34:39

## Scenario:
You're assigned a task to create an S3 bucket, with a time stamp to ensure it's unique, enable static website hosting, whilst the bucket must be private. Explore Cloudfront to privately expose your index.html file in your S3 bucket, and ensure it's accessible via a secured custom domain name.

## Essentials:
* An AWS Account.
* Be logged in an IAM user with Admin priviledges.
* Files for the static website 
* A custom domain name. 
    * If you dont have, get a free domain name from [freenom](https://www.freenom.com/en/index.html?lang=en)
<figure>
  <img
  src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h9dsjpocr094cdftfj9d.png"
  alt="Deployment architecture.">
  <figcaption>Figure 1: Cloudfront and S3 Deployment Architecture</figcaption>
</figure>

Figure 1 explains the deployment architecture.
* A Private Amazon S3 bucket containing files for the static website to be hosted 
* CloudFront caches the  S3 private pages and distributes the content to its default URL
* CloufFront is linked to the custom domain name(wandexdev.me) via Hosted zone in Route 53.
* The connection is secured via SSL and Certificate Mangaer 
* Users can access the static website by simply navigating the custom domain name(wandexdev.me)

## Steps to achieve the setup
### Step 1: Create an S3 bucket with private Access
* Navigate to your home console on your aws account, select Northern Virginia (us-east-1) as your region. This is optional and done to stay within the free tier limits of the aws account
* Move to the S3 console either by searching for S3 in the search bar or by clicking S3 in 'recently visited services'
* Select create Bucket in Figure 2 below.
<figure>
  <img
  src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ryhu14z0i7pi7ruyov3y.png"
  alt="Create Bucket.">
  <figcaption>Figure 2: Create a bucket in S3 console</figcaption>
</figure>
* Set up Bucket Configuration. Refer to figures 3, 4, 5
    * Give a bucket name. The name has to be unique, no spaces or uppercase letters present, avoid using dots(.), hyphens(-) are more welcome. Using Timestamps helps relieve the stress.
    * Region is US East (N. Virginia) as previously mentioned
    * Leave Object Ownership as default
    <figure>
        <img
        src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mbkxkm4n7d0dle9nimog.png"
        alt="Bucket Details">
        <figcaption>Figure 3: Bucket Name, Region and Object Ownership</figcaption>
    </figure>
    * Leave Public Access blocked as we want our bucket private
    * Enable Versioning if you would like to still make changes to the static files you're about to upload but still have older versions uploaded, keep it Disabled if not. 
    * Tags are not neccessary for this simple static website demo
    * Server-side Encryption is automatically applied so we leave encryption to default 'Amazon S3-managed keys'. The Encryption enables S3 encrypt objects before saving it and decrypts it when downloaded. Encryption doesn't change the way that you access data as an authorized user.
    * Disable Bucket key as we are not using KMS encryption
    click on Create bucket
    <figure>
        <img
        src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/vgdw6i6pnbaa0p3cpv5m.png"
        alt="Bucket Details">
        <figcaption>Figure 4: Public Access, Bucket Versioning and Encryption</figcaption>
    </figure>
        * Observe and verify new bucket details (name, region, bucket access etc) and ensure no error was made
        <figure>
            <img
            src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/376l3805k5nmllxnq9a8.png"
            alt="Bucket Details">
            <figcaption>Figure 5: New Bucket details</figcaption>
        </figure>

### Step 2: Upload static website files into S3 bucket created.
* Select the bucket name just created
* Select Upload, then select add files
* Add all files needed to run the static website from your local device
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eg13x9baslnwgpvw67si.png"
    alt="Upload Details">
    <figcaption>Figure 6: Pre Upload Details</figcaption>
</figure>
* Leave other options at default
* Select Upload
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hfzqpaa4g4vqr68fw6tb.png"
    alt="Upload Details">
    <figcaption>Figure 7: Uploaded Bucket Details</figcaption>
</figure>

### Step 3: Enable Static Website Hosting
* Select Bucket name, then Properties
* Move down to the very last option 'static website hosting' and select Edit
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/t1pd9l01yaszcm6nyc5o.png"
    alt="Web Static Hosting">
    <figcaption>Figure 8: Static Website Hosting Section</figcaption>
</figure>
* Select Enable and a new interface shows.
* Select host static website. A Static website is made up of individual webpages that contain static / unchaging content. Enabling your S3 bucket as a static website mean the website is available at the specific AWS Region website endpoint of the S3 bucket.
* Specify the home page of the website files i.e index.html
* Save changes
* Success message
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/3xk9p1ili7ejw8ztgck6.png"
    alt="Web Static Hosting">
    <figcaption>Figure 9: Successfully Enabled</figcaption>
</figure>

### Step 4: Set up Hosted Zone and name servers in Route 53
* Move to the route 53 console either by searching for Route 53 in the search bar or by clicking Route 53 in 'recently visited services'
* Click create hosted zone
* Input your custom Domain name in the Domain name field
* Select Public hosted zone as Type
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u7umb0ovwsxk546zj8to.png"
    alt="Hosted zone">
    <figcaption>Figure 10: Hosted Zone Created in Route 53</figcaption>
</figure>
* Click on the hosted zone. The ns- values under the Value/Route traffic to are called name servers
    * To link custom domain name with route 53, the name servers from route 53 have to be updated on custom domain name provider's management.
    * The name servers generally tell the domain name to redirect requests to it.
    <figure>
        <img
        src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/l406a8cxluyw65qhlvxo.png"
        alt="Name Servers">
        <figcaption>Figure 11: List of Name servers generated</figcaption>
    </figure>
* Switch to a new tab in your browser (do not close the Route 53 page with the nameservers), log in your custom domain provider's site and add name servers
    * Mine is namecheap.com, log in, select domain list, then manage
    * Navigate to custom DNS, select add name server and add all four name servers from Route 53 without the last dots!(.)
    * Save changes
    <figure>
        <img
        src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qwbkgcg7ycg661bq9l2o.png"
        alt="Name Servers">
        <figcaption>Figure 12: Name servers in Domain Providers site</figcaption>
    </figure>

### Step 5: Set up an SSL certificate via the AWS Certificate Manager
* Setting up an SSL certificate ensures CloudFront custom domain with SSL is secured.
* Move to the Certificate Manager console either by searching for Certificate Manager in the search bar or by clicking Certificate Manager in 'recently visited services'
* Select Request a public certificate and then Request a certificate.
* Input your custom Domain name i.e wandexdev.me
* Choose DNS validation as method of validation.
* Select next till you can confirm and request certificate
* It then displays 'pending validation' on next page. This would be fixed by linking the certificate with Route 53
* Click Certificate ID
* Next click on Create record in Route 53 button under Domains.
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rzctg2c5kqi671relcqz.png"
    alt="SSL Cetificate">
    <figcaption>Figure 13: Link Pending SSL Certificate with Route 53</figcaption>
</figure>
* click create records
* Certificate Manager takes a while before certificate is issued so please be patient.
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/h95eb6523m24ptpy2rbl.png"
    alt="SSL Cetificate">
    <figcaption>Figure 14: Issued SSL Certificate</figcaption>
</figure>
* Once certificate is issued, CloudFront Distribution can be set up.

### Step 6: Set up CloudFront Distribution
* Move to the CloudFront console either by searching for CloudFront in the search bar or by clicking CloudFront in 'recently visited services'
* Select create Cloudfront distribution in Figure 15 below.
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/gky8235u6hqffldo696w.png"
    alt="CloudFront">
    <figcaption>Figure 15: Create CloudFront Distribution</figcaption>
</figure>
* Click on Origin domain and select the name of S3 bucket created from drop down list i.e wandebucket-0432pm.s3.amazonaws.com. Its simply the source from which CloudFront caches from.
* Origin Name automatically fills up
* Select Legacy access identities for Origin access. Origin Access is mainly for restricting access of a S3 bucket to only authenticated requests from CloudFront. An OAI(Origin Access Identity) would be used to do this
* Select Create new OAI
    * An autogenerated name shows in the prompt, click create
    <figure>
        <img
        src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e97njclcnul7rhqs1iog.png"
        alt="Cloudfront">
        <figcaption>Figure 16: Origin Access Identity (OAI)</figcaption>
    </figure>
    * Select yes, update bucket policy as in Figure 17 below
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mxmh0mhjeos5246soo76.png"
    alt="CloudFront">
    <figcaption>Figure 17: CloudFront Configuration</figcaption>
</figure>
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6v8l3nwxa5jvxe6urit1.png"
    alt="CloudFront">
    <figcaption>Figure 18: CloudFront Configuration</figcaption>
</figure>
* Select to Redirect HTTP to HTTPs
* Scroll down to Alternate Domain Name (CNAMEs) under Settings section then type in your custom domain name i.e wandexdev.me
* Still under settings, select the drop down list for Custom SSl certificate and select your issued certificate for your domain name.
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/72zbp6s94iqro4k336qp.png"
    alt="CloudFront">
    <figcaption>Figure 19: CloudFront Configuration</figcaption>
</figure>
* Scroll to Default root object and write index.html in the box
* Create distribuition
* The Distribution takes a while to deploy so be patient
    * Once provisioned, status changes to deployed and state turns Enabled.

### Step 7: Link Custom domain with CloudFront via Alias in Route 53
*  Move to the route 53 console either by searching for Route 53 in the search bar or by clicking Route 53 in 'recently visited services'
* Select your domain name in Hosted zone
* Click Create record, choose Simple routing, turn Alias on.
* Select the drop down menu at Route Traffic to and choose Alias to CloudFront distribution
* Click drop down list and select cloudfront distridution
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/qe9ljz1zyvjyyjpesm37.png"
    alt="Alias Record">
    <figcaption>Figure 20: Create an Alias Record for CloudFront</figcaption>
</figure>
* Wait a few minutes for the DNS records to be updated
* Type in your custom domain name in a browser and you would see your static website ONLY distributed and accesible via by cloudfront.
Here's mine!!
<figure>
    <img
    src="https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pp4uqkvd47qzncd92sja.png"
    alt="My Chess Static website">
    <figcaption>Figure 21: Final Output showing my static website</figcaption>
</figure>

### Remarks
* I hope you found this guide helpful and as enjoyable as I enjoyed making it. Ask me questions in the comment section and I'll surely respond.
* *I used [app.diagram](https://app.diagrams.net) to draw my architechture diagram and its free!*
* Please dont forget to delete all AWS resources provided after youre done. Staying within the free tier limits is low cost friendly