- Published on
Guide to Deploying an SSG Site with CloudFront
Overview
This guide explains how to deploy a site created with Static Site Generation (SSG) to AWS CloudFront. CloudFront enables efficient, fast access to your site across multiple locations without requiring a dedicated server. However, there are specific steps to consider during deployment: removing .html extensions from files and setting the root file as index.html are crucial.
Route 53 - Hosted Zones
- Create a new record using "Create hosted zone."
- Enter "a.com" in the "Domain name" field.
Domain
- Update the "Name Server" settings at your domain provider with the Name Servers from the Hosted Zone created in Route 53.
AWS Certificate Manager (ACM)
- Request a new certificate using the "Request" option.
- Enter "a.com" as the "Fully qualified domain name" in the "Domain names" section.
Route 53 - Hosted Zones
- For the "a.com" domain, add a new record with "Create record."
- Select "CNAME" as the "Record type" and enter the "CNAME value" from the certificate details in the "Value" field.
- Once the certificate is verified, its "Status" will display as "Issued."
S3 Bucket
- Create a new "bucket" using "Create Bucket."
- Name it "blog" in the "Bucket name" field.
- In the "Block Public Access settings for this bucket" section, uncheck "Block all public access."
- After creating the bucket, add the following policy in the "Permissions" tab:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::blog/*"
}
]
}
Cloudfront Functions
- Create a function by selecting "Create function."
- Name it "htmlredirect."
FunctionCode
function handler(event) {
var request = event.request;
var uri = request.uri;
if (uri !== '' && uri !== '/' && uri.indexOf('.html') === -1) {
request.uri = uri + '.html';
}
return request;
}
- Go to the "Publish" tab and select "Publish function."
Cloudfront Distributions
- Create a new distribution using "Create distribution."
- Select the "blog" S3 bucket as the "Origin domain."
- In the "Function associations" section, choose "Viewer request" as "Function type" and select "htmlredirect" for "Function ARN / Name."
- In the "Settings" section, select the "a.com" domain certificate under "Custom SSL certificate."
- Set "index.html" as the "Default root object."
- Note the "Distribution ID" and "User ID" in the ARN section of the distribution.
Route 53 - Hosted zones
- Add a new record for the "a.com" domain using "Create record."
- Select "A" as the "Record type" and mark "Alias."
- Under "Choose Endpoint," select "Alias from CloudFront distribution" and choose your distribution.
Identity and Access Management (IAM) - Policies
- Create a new policy using "Create policy."
Policy
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:ListBucket",
"s3:GetObject",
"s3:PutObject"
],
"Resource": [
"arn:aws:s3:::blog",
"arn:aws:s3:::blog/*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation",
"cloudfront:GetInvalidation"
],
"Resource": "arn:aws:cloudfront::{USER_ID}:distribution/{DISTRIBUTION_ID}"
}
]
}
- Name the policy as "cicdpolicy".
Identity and Access Management (IAM) - Users
- Create a user with "Create user."
- Set "User name" as "cicd."
- Assign permissions using the "cicdpolicy" created in the previous step.
- After adding, go to the "cicd" user.
- In the "Security credentials" tab, create an access key by selecting "Create access key."
- Choose Command Line Interface (CLI).
- Note the "Access ID" and "Access Key."
- In the "Security credentials" tab, create an access key by selecting "Create access key."
CICD
- Download the static site application: For example, you can use the Next.js Starter Blog project.
- Add a "Github Workflow" to the project.
.github/workflows/aws.yml
name: AWS CI
on:
push:
branches: ["main"]
pull_request:
branches: ["main"]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: "yarn"
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Build project
env:
EXPORT: 1
run: yarn build
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.CICD_AWS_ACCESS_ID }}
aws-secret-access-key: ${{ secrets.CICD_AWS_ACCESS_KEY }}
aws-region: eu-west-1
- name: Sync with S3
run: aws s3 sync ./out s3://${{ secrets.CICD_AWS_S3_BUCKET }}
- name: Invalidate CloudFront cache
run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CICD_AWS_DISTRIBUTION_ID }} --paths "/*"
- In the GitHub Settings under Secrets and variables, add the following values:
- "CICD_AWS_ACCESS_ID": Access ID for the cicd user
- "CICD_AWS_ACCESS_KEY": Access Secret for the cicd user
- "CICD_AWS_S3_BUCKET": blog
- "CICD_AWS_DISTRIBUTION_ID": CloudFront distribution ID
After completing these steps, your SSG site will be automatically deployed through AWS CloudFront.