Hugo is an amazingly simple static site generator. It’s been gaining increasing popularity over the last few years and it’s my chosen framework for my website.
Let’s see how I host JeremyRitchie.com.
This is part one of a two part series about hosting Hugo on AWS. I’ll be using the AWS CLI (where sensible) in this series, just to mix things up a bit.
Today i’ll cover creating a S3 bucket, deploying Hugo to S3, using Cloudfront as the CDN and using a custom domain.
Next week i’ll cover CloudFront Functions and Origin Access Control.
This blog is all about the AWS side of a Hugo Website, so let’s skim over a hugo quickstart and get into the fun AWS bits ASAP.
hugo new site quickstart
cd quickstart
git init
git submodule add https://github.com/theNewDynamic/gohugo-theme-ananke themes/ananke
echo "theme = 'ananke'" >> config.toml
hugo server
Looks like it worked!
See Add Content section of the quickstart guide to see how to add content to your new site.
Today i’m going to leave it there and move on to the AWS side.
First we need to create a bucket to host our website.
aws configure
or aws configure sso
if AWS SSO is setup on your AWS Organization.
aws s3 mb s3://jeremyritchie-demo-hugo
Replace jeremyritchie-demo-hugo
with the name you want your bucket to be.
aws s3 website s3://jeremyritchie-demo-hugo --index-document index.html
Add deployment target to config.toml
[[deployment.targets]]
name = "default"
URL = "s3://jeremyritchie-demo-hugo?region=ap-southeast-2"
Now let’s deploy the website to S3!
cd quickstart
hugo
hugo deploy
So let’s test!
http://jeremyritchie-demo-hugo.s3-website-ap-southeast-2.amazonaws.com/
Damn, what’s going on?
Our bucket has default permissions. This means the bucket policy is empty, and therefor, is not publicly accessible.
Let’s fix this.
echo '{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicRead", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject", "s3:GetObjectVersion" ], "Resource": "arn:aws:s3:::jeremyritchie-demo-hugo/*" } ] }' >> policy.json
aws s3api put-bucket-policy --policy file://policy.json --bucket jeremyritchie-demo-hugo
Don’t forget to keep replacing jeremyritchie-demo-hugo
with your own bucket name!
Let’s test that same URL again:
http://jeremyritchie-demo-hugo.s3-website-ap-southeast-2.amazonaws.com/
Now you could stop there, you have the website in AWS. But today we’re going to take it a step further and put a CDN in front of it - CloudFront.
NB: Default root object
Same as S3, we want CloudFront to invisibly redirect website users to the index.html file with they load the root of the website.
We’ll touch on this point more in the next post!
Let’s go have a look at the website now!
https://d12ra6jchsinq8.cloudfront.net
First, we need to own a domain.
I already do, you’re looking at it. If you don’t, i suggest doing some more research on what you want and if it’s available.
You can buy them directly from AWS in Route53.
I’m going to assume you already have a domain, and a public hosted zone setup in AWS like so:
Now you’ve got a domain in Route53, we need to register an ACM certificate in the us-east-1
region. This is very important you get the correct region.
aws acm request-certificate --domain-name demo.jeremyritchie.com --validation-method DNS --subject-alternative-names www.demo.jeremyritchie.com --region us-east-1
Return Code:
{
"CertificateArn": "arn:aws:acm:us-east-1:747340109238:certificate/fde6600b-3t79-ye0c-a4p1-380example"
}
Now let’s add the DNS entry to validate it!
At this point i’m going to let you know there is a button in the console to do this. Like literally, one click. Let’s do that!
Let’s update CloudFront with the certificate.
Finally, we need to add an A record to Route53 to direct demo.jeremyritchie.com to our Cloudfront distribution.
Finally, it looks like demo.jeremyritchie.com is working!
We want our Hugo links to navigate to the correct URL right? Let’s make sure that happens.
baseURL = 'https://demo.jeremyritchie.com/'
languageCode = 'en-us'
title = 'My New Hugo Site'
theme = 'ananke'
Amazing! We were able to create a brand new website, host it on S3, and then put a CDN (CloudFront) in front of it for better performance and availability. Then we put a custom domain over the website for that professional look!
Catch me next week for Part 2.
In Part 2 I’ll cover:
All the source code is available on my GitHub.