This is part two of a two part series about hosting Hugo on AWS.
In Part 1 I deployed the Hugo website to S3, and put cloudfront in-front of it. Today i’ll:
OAC provides a secure way to access S3 origins to CloudFront. It’s the successor to OAI (Origin Access Identity) as it provides a number of improvements over OAI including comprehensive HTTP method support, S3 KMS encryption support and more.
We need to secure our S3 bucket and restrict access to the website strictly via S3.
Should be simple. Let’s create the OAC via AWS CLI.
aws cloudfront create-origin-access-control --origin-access-control-config Name="demo-site",Description="demo hugo website",SigningProtocol="sigv4",SigningBehavior="always",OriginAccessControlOriginType="s3"
And now we plug it into CloudFront.
Let’s follow that link and overwrite the bucket policy.
Great! So let’s test.
Attempting to access the S3 static site directly
http://jeremyritchie-demo-hugo.s3-website-ap-southeast-2.amazonaws.com/
However if we access cloudfront via demo.jeremyritchie.com
CloudFront Functions are a compute platform where you can manipulate the request/response data for your website. Examples such as shortening URL’s, redirects, adding cookies or headers, etc.
Cloudfront Functions are very very similar to Lambda@Edge, but provide faster latency and lower cost, and the cost of flexibility and execution time. Check out this post here.
So why do I need them?
Well let’s add a post to our demo website
hugo new posts/my-first-post.md
echo "my first post" >> content/posts/my-first-post.md
hugo --buildDrafts
hugo deploy --force
The post is not working?!
Let’s try a slightly different URL:
https://demo.jeremyritchie.com/posts/my-first-post/index.html
What’s going on here is what you expect from SSG (Static Site Generators) - It’s taking complex input from themes and markdown and more, and using it to generate a static file structure of html files.
The consequence is that for any publicly visible URL, there must be a filesystem entity (either a file, or a directory containing an index.html file). This means loading demo.jeremyritchie.com
needs to implicitly load demo.jeremyritchie.com/index.html
That’s easy, because on S3 you set a index document, and on Cloudfront, we configured a Default Root Object
.
When it comes to a post, we’re no longer being helped by built-in redirection provided by S3 or CloudFront. We need to build it our self.
We know Hugo likes to add a trailing /
to each page. But we need it to end in /index.html
instead.
That’s where CloudFront Functions come in. Let’s check it out!
function handler(event) {
var request = event.request;
var uri = request.uri;
// Logging
console.log(request)
// Check whether the URI is index.html
if (uri.endsWith('/')) {
request.uri += 'index.html';
}
// other custom redirects
else if (uri.endsWith('blog') || uri.endsWith('jeremy-ritchie')) {
request.uri += '/index.html';
}
return request;
}
Add this code to the function and then publish it.
After publishing, you are able to associate it to a distribution:
Alright! We’re associated that Function.
Let’s retest https://demo.jeremyritchie.com/posts/my-first-post/
Holy macaroni! We’ve done it.
We’ve both locked down the website to CloudFront only, and added some wicked cool Functions that run at the edge!
For more reading about Hugo + CloudFront OAC + index.html issue. Check out this link: https://aws.amazon.com/blogs/compute/implementing-default-directory-indexes-in-amazon-s3-backed-amazon-cloudfront-origins-using-lambdaedge/