How to create a secure static Hugo website hosted in S3 with a custom URL

I created this website using GoHugo a static website generator with posts written in markdown language. Hugo is a bit of a shock to the system after 9 years using Blogger; I wanted the freedom to create my own site but without needing to build from scratch. Hugo removes some of the complexity of creating a website and allows me to focus on the content and a smattering of styling. I wanted to be able to host my own static website from an S3 bucket in Amazon’s AWS and this is how you can do the same.

Create your static website using GoHugo

I won’t go into details here of how to create your static website but if you’d like to find out more about creating a Hugo website, I found the Getting Started Tutorial to be a good starting point. Once you have the files you need for your static website you are ready to configure AWS.

Register your custom domain

I chose to register with AWS because I knew I’d have everything I needed in the AWS Route53 console within seconds of registering my domain. The instructions below assume you registered a domain with Route53. To register a new domain, follow the instructions on the AWS website.

Create two S3 buckets

You will need to create two S3 buckets to host your website, named with the apex root of your custom domain. In my case I created one each for:

  • Upload the content for your Hugo website into your primary S3 bucket (the one without the www). If you’re going to regularly update your website content, you will want to automate this process!

    The AWS tutorial for enabling static website hosting walked me through the process of enabling static website hosting. Each bucket needs to be explicity configured for static website hosting and a bucket policy applied so that the files in your website are publicly accessible. The www bucket needs to be configured to redirect requests to your primary bucket which is the one that hosts the files for your website.

    The important thing to know is that you will need to configure the landing page and error page when setting up your static website hosting rules for the primary bucket. I am using the ananke Hugo theme which creates an error file called 404.html so I needed to override the default value assumed by S3.

    Create a custom SSL certificate

    If you want your readers to avoid annoying browser security warnings every time they visit your website, you will want to be able to serve your webpages over HTTPS and to do this effectively, you’re going to need an SSL certificate that tells the browser your content is from a trusted source. If you have an SSL certificate already, you can import it into the AWS Certificate Manager. If not, the process of requesting one is short and surprisingly pain-free.

    • Inside the AWS console, visit the Certificate Manager service (find it in the Security, Identity & Compliance group) and request a new certificate.
    • You want to request a public certificate.
    • Add both domain addresses (with and without the www.) to the certificate request and click next.
    • When prompted, allow the certificate manager to automatically create validation records in your Route53 domain (this saves you having to manually add and validate records in Route53).
    Once complete, your certificate may take anything from a few seconds to a few hours to be issued. Mine took about 10 minutes.

    Create a CloudFront distribution

    To host your website over HTTPS (and to make it a super-speedy experience for your readers) you now need to set up an AWS CloudFront content distribution. CloudFront caches the content of your website on a local AWS edge location when people request it, this saves having to make full round-trips to your S3 bucket for content that rarely changes. The CloudFront distribution is also a quick and easy way to ensure that ALL requests to your website operate over HTTPS rather than HTTP.

    • In the AWS console visit the CloudFront service found under the Networking and Content Delivery group.
    • Create a new distribution - choose the “web” option when prompted on the Get Started page.
    • WARNING - THIS IS THE MOST IMPORTANT PART OF THESE INSTRUCTIONS! When you configure your CloudFront origin, you will be presented with a drop-down list which allows you to select the name of the S3 bucket that you want to be the source of your content. DON’T USE THE DROP-DOWN. Instead, go back to your primary S3 bucket and copy the website URL from the static website hosting screen (in the screenshot above) and copy and paste this into the Origin field in your new distribution.
    • Alter the Viewer Protocol Policy to Redirect HTTP to HTTPS.
    • Scroll down to the distribution settings; add both domain names (with and without the www) to the Alternate Domain Names box, separated on a new line.
    • Choose to use a Custom SSL Certificate; the screen should auto-populate with your SSL certificate (unless you have more than one, in which case use the drop-down list).
    • Finally, make sure that the Default Root Object setting contains the name of your index page e.g. index.html.
    • Retain the defaults for all other fields on the page and then choose to “Create Distribution” at the very bottom of the page.
    Your CloudFront distribution could take some time to initialise - mine took over 30 minutes.

    Apply Alias Records for your domain

    The final piece of the puzzle is to alter the records for your Route53 domain so that any requests to your domain name ( or are routed to your Cloudfront distribution, which in turn serves the content from your S3 bucket.

    • In the Route53 console, navigate to your Hosted Zone and add two new Record Sets. One for your apex root ( and one for the www version (
    • The Record Sets should both have a Type of “A - IPV4 Address”
    • The Record Sets should have the Alias Target set to the cloudfront distribution address (if your distribution is ready, you should be able to select this from the drop-down list).
    • Use a Simple Routing policy for both Record Sets.
    Your Route53 record sets could take time to propagate (although usually I find it is more or less instant!)

    Test your website

    Navigate to or and you will notice that you are always redirected to

    Et voila, your custom Hugo static website is now hosted wholly in AWS and all traffic is secured using HTTPS. Remember, if you are actively updating your website and want to see the changes appear online you will need to invalidate the cached copy of your files that Cloudfront has stored. To do this, open the Cloudfront distribution in the AWS console, navigate to the “Invalidations” tab and add a new validation for the path “/*” to remove all of your website’s content from the cache. It takes a couple of minutes for the cache to be cleared.

    comments powered by Disqus