Deploying a Static Website to S3 using Hugo


After deciding to launch this blog a few months ago, I was faced with the choice of how to best host and run a small website. Luckily for me, I found a whole host of options using a bunch of different technologies. Ultimately, I decided to use Hugo - a popular static site generator. What’s awesome about Hugo is that it can be used as part of a severless architecture that keeps everything cheap and super fast - let’s take a look at how to set it up!

Writing with Hugo

Why use a Static Site Generator?

One of the biggest considerations when creating a personal website is whether or not to use a dynamic or static site. Dynamic sites (like those produced by Wordpress, Drupal, Django, and more) rely on a site engine that is able to serve content dynamically to users. In this configuration, every request to the site is received by the server software, which “whips up” and sends back the latest version of the requested page to the user. This is great for websites that are updated frequently and integrate content from a number of different sources. However, the need to have a server backend constantly available and serving the site means there is a bit of a barrier to entry for the average user, as well as other technological challenges to ensuring high performance and availability.

Dynamic vs Static Sites

Unlike static sites, which generate and serve content dynamically as requested, static site generators create the entirety of the website (all pages, directories, and links) up front. That way, the HTML code produced by the generator can be placed anywhere on the internet and can be viewed simply by navigating to the main index.html which is produced. What is awesome about this is that static site generators can be used in conjunction with storage services like Amazon S3 - placing the latest version of your site in a publicly available S3 bucket is all you need to have a website that’s fast and always available.

For some more context, check out this post on the differences between WordPress and Jekyll, a popular static site generator.

Using Hugo

Though I considered using Jekyll, I ended up using Hugo as the static site generator for my blog. Hugo has an awesome quick start that breaks down how to install the application and quickly create a new site, and is super easy to get running with quickly. Plus, Hugo’s awesome themes library means it’s easy to get and change the theme and design of your site.

Hugo Themes

My writing workflow in Hugo looks a lot like the following:

  1. Write post using Markdown: hugo new post/
  2. View post using local web server (http://localhost:1313, and tweak post as necessary: hugo server -D
  3. Build site to publish posts: hugo -v

Deploying to S3

Amazon S3 (Simple Storage Service, get it?) is an incredible tool for hosting static websites. Basically, it allows you to turn any of your storage “buckets” into a website by intelligently re-writing your URL requests to the appropriate HTML pages in your bucket. To access this functionality, you just need to turn on static web site hosting.

This is an awesome way to host your website for a few reasons:

  • S3 basically never goes down (because when it does, it’s national news)
  • You don’t need any servers to host your site
  • Your website is infinitely scalable (because AWS is responsible for making S3 buckets available regardless of load)
  • It’s dirt cheap: S3 storage is 2.3 cents per Gigabyte per month
  • You can link an S3 bucket to a domain name using the Route 53 DNS service

Configuring your S3 Buckets

  1. Create an S3 bucket using the domain name of your site. For me, that means

  2. Make sure versioning is turned on

  3. Enable static website hosting, and specify index.html as the index page for your site

    S3 Static Website Hosting

  4. Attach a bucket policy to allow public reads

        "Version": "2008-10-17",
        "Statement": [
                "Sid": "AllowPublicRead",
                "Effect": "Allow",
                "Principal": {
                    "AWS": "*"
                "Action": "s3:GetObject",
                "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"


  5. Create another S3 bucket with your domain name prefixed by “www.” - for me, the bucket is

  6. In the bucket properties, use the static website hosting section to enable request redirection. Enter your first bucket (ie. as the target

    S3 Bucket Redirect

Configuring Route 53

Now that you’ve got your S3 buckets configured, you can point your domain name to your S3 site using Route 53.

  1. Purchase (or import) a registered domain with Route 53 (I bought the domain from Route 53)

  2. Create a Hosted Zone using your domain name

  3. Create an Alias record for your domain, selecting your main S3 bucket as the target

  4. Create another Alias record for your “www” domain, pointing at the “www” S3 bucket

Once set up, your hosted zone entries should look something like what’s below:

Route 53

Uploading your Site

Now that you’ve got your S3 buckets set up and domain configured, all that’s left is uploading your site!

  1. First thing, build your site one more time on your computer using hugo -v. The files you’ll be moving are in the public directory and update each time your site is built

    Building your Site

  2. Copy the contents of the public directory into your main S3 bucket. You can do this via the AWS CLI, but the easiest way is probably to CTRL+A all the files and folders within your public folder and drag and drop them into your S3 bucket, hitting “Upload” in the bottom left when the dialog window pops up

  3. Once the upload completes (things should look something like the image below), navigate to the base URL of your site and you should be live!

S3 File Browser

Next Steps

In part 2 of this article, we’ll take a look at how to build a continuous delivery pipeline that takes that removes the manual building and drag/drop S3 uploads, letting you focus only on the writing!