Recently, I decided to renew my silentYak blog and recreate it as a static website built using Zola and deployed to S3 with CloudFront. These are the ultra-brief cliff notes on what to do in case you want to set up something similar for yourself.
- Create the source code
Q
(example) of the blog using Zola. - Create the GitHub repository
S
hosting the source codeQ
of the blog. - Create a private S3 bucket
B
to which artifacts will be published. - Create a hosted zone
H
in Route 53 for your domainM
. - Update your domain registrar to use Route 53’s nameservers for domain
M
. - Wait for the hosted zone
H
in Route 53 to become authoritative. - Request a new certificate
X
for your domainM
from AWS Certificate Manager (ACM) in us-east-1 (CloudFront has this constraint on AWS region). - Create domain verification (TXT) records in hosted zone
H
as prompted by ACM. - Wait for the requested certificate
X
to be issued. - Create a CloudFront function
F
to redirect toindex.html
files correctly (example). - Create a CloudFront distribution
D
with certificateX
, “Viewer Request” functionF
, and alternate domain nameM
(not optional). - Update hosted zone
H
to create A and AAAA aliases for distributionD
. - Update S3 bucket
B
‘s access permissions to authorize CloudFront distributionD
. - Create an OpenID Connect identity provider
C
to represent GitHub Actions. - Create an IAM policy
P
(see below) for allowing access to S3 and CloudFront. - Create an IAM role
R
for publishing artifacts. - Associate the IAM policy
P
with the IAM roleR
. - Associate a trust policy
T
(see below) with roleR
for GitHub Actions. - Generate a GitHub Actions workflow file
W
(example) to build and publish artifacts. - Commit the GitHub Actions workflow file
W
to the GitHub repositoryS
.
Example IAM Policy P
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement0",
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:ListBucket",
"s3:DeleteObject",
"cloudfront:CreateInvalidation"
],
"Resource": [
"arn:aws:s3:::silentyak-com-website-assets/*",
"arn:aws:s3:::silentyak-com-website-assets",
"arn:aws:cloudfront::965356658022:distribution/E2JDATP1TDIY9S"
]
}
]
}
Example Trust Policy T
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::965356658022:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:rri/silentYak:ref:refs/heads/main"
}
}
}
]
}
That’s all for today, folks! 🖖