Skip to main content
  1. Articles/

Host Hugo on S3 + CloudFront

·3 mins

This site uses Hugo, with the Congo team.
I won’t bother you on how to use Hugo, write articles in markdown format, or how to configure your theme; there are already good articles online (Congo theme documentation was a good start for me, and in a day, everything was online)

Why CloudFront + S3 #

The key for me is simplicity and using what I know best. This side blog is a personal learning project, but I don’t want to focus on the tools I use to write. I need to get the job done and have time to learn other things and write articles, so here it is: the basic exercise you do when you approach AWS Cloud Managed services is really something you can do.
For Hugo, you need to pay attention to a peculiar feature of CloudFront and S3: the default page (index.html) is valid only for the root of your website, not for the “subfolders” (do you know that the concept of folder does not exist in S3, right? If you don’t know, S3 has a flat namespace). So, if you deploy your website after configuring these two services, you’ll find out that only the homepage works, and if you click on an article in a subfolder, you will get the dreaded “No such key” error.
We will see how to fix this issue with CloudFront functions later.

Deploy CloudFront and S3 #

You can use the solution from AWS for a quick deploy, or follow this tutorial if you are not familiar with CloudFormation and you want to learn how to use the AWS Console

Once you have your website configured, we will need to add a tiny part.

Configure the CloudFront function to make Hugo subdirectories work #

CloudFront doesn’t behave as Apache or Nginx, so it will search for index.html only on the “root” of your website, giving a “keynotfound” error if you try to access a subdirectory (like /blog/categories).
Lucky for us, CloudFront Functions exist and can help. AWS already has a repository for standard use cases.
Pro tip: explore the aws-samples repositories full of hidden gems.
We will use the URL rewrite to append index.html to the URI for single page applications example.
Here’s the code, for simplicity:

async function handler(event) {
    var request = event.request;
    var uri = request.uri;
    
    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    } 
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}

Create the CloudFront functions #

  1. Go to the CloudFront console, select “CloudFront functions from the left menu.
    CloudFront Menu
    .
  2. Create the function, give it a name, a description, and select 2.0 as the JS version.
    CloudFront Menu
  3. Paste the function code.
    CloudFront Function Code
  4. Publish the code
    CloudFront Function Publish Code

Associate the CloudFront Function with your website #

  1. On the CloudFront console, select your distribution and click on the behaviors tab
    CloudFront behavios tab
  2. Select the “Default” (it should be the only one), click “Edit”, and go to the bottom of the page. Select the “Viewer request”, select “CloudFront function from the dropdown menu, select your function
    Select CloudFront Function on Viewer Request

You’re all set! Happy blogging with Hugo!

Wait, and how do I deploy?

Deployment #

You can use a pipeline, like GitHub Actions or CodePipeline. I prefer the “old and dirty” method: sync files Since I don’t write every day, I don’t feel the urge to have an automatic deployment mechanism, so to update my website, I run:

hugo publish
aws s3 sync --delete static/ s3://mywebsitebucket/

This will sync (a la rsync) my content to the S3 Bucket, deleting old assets, and I’m all set! Lazy, but it works!

Damiano Giorgi
Author
Damiano Giorgi
Ex on-prem systems engineer, lazy and prone to automating boring tasks. In constant search of technological innovations and new exciting things to experience. And that’s why I love Cloud Computing! At this moment, the only ‘hardware I regularly dedicate myself to is that my bass; if you can’t find me in the office or in the band room try at the pub or at some airport, then!

comments powered by Disqus