Choosing your Technology Stack
So you'd like to set up your own blog? Thankfully, there are quite a few options available to you. While this blogpost will guide you on setting up a static blog using Hugo and AWS, it's not the only way. I'm including 3 major decisions that you should consider carefully
Decision 1: Custom Domain?
Do you want your website to have a custom name? If not, you can probably set up something super quick using Github pages (for a website name that's relatively readable). If you do want a custom domain, you'll have to buy it from a domain registrar
Decision II: Static vs Dynamic Hosting
Another key decision you will have to make is whether you want to host a static or dynamic website.
Static sites follow a very simple model. There's a bunch of html files and a server that displays them. That's it. You change the html files (or add more), point the server to these changes and they're live. It's an easy model, and something that's perfect for a blog.
Dynamic sites are a bit more complex. If you've ever come across a wordpress or ghost website - these are dynamic. There's usually a more granular configuration mechanism, and correspondingly more resources are required to host/serve the website. If you don't need advanced CMS management, or lots of server-side processing for events - dynamic sites are overkill in terms of potential functionality.
I tried both, and have chosen the static flow in the end for a more automated workflow (though dynamic hosting was easier to set up). If you'd like to go down the dynamic hosting route via AWS, I've included a very brief guide here:
Dynamic Hosting Simple Guide |
---|
Buy a custom domain |
Set up a Ghost EC2 instance |
Attach an ElasticIP to the EC2 instance |
Create a DNS CNAME "A" entry on your domain DNS management portal and link to your ElasticIP |
Decision III: Where to store your website files
You can use any of the major cloud providers - they're all pretty good. Each has its pros and cons that I won't cover in this guide.
I went with AWS because of their free SSL certificates and Route53/Cloudfront stack. Also, quite importantly, their documentation
is top notch (ever the unsung hero)
Yosh! Let's set up our website
This guide will show you how to set up a static website using
-
A custom domain name
-
Static Website Framework - Hugo
-
AWS as the place to store my website files
Here are the steps we'll follow in order to set up the site. If you've already completed any of the steps, feel free to jump to the section that's relevant to you:
Overview of Guide |
---|
1. Buy a custom domain |
2. Set up an S3 bucket,configured for Public Access |
3. Create a simple Hugo website |
4. Install AWS CLI |
5. Configure your Hugo deployment to upload to S3 |
6. Set up Route53 |
7. Set up SSL (Optional) |
Note: I've tried my best to keep this guide as simple as possible, but you will need to be comfortable with running commands on the terminal. Knowledge of tinkering with config files also comes in handy. With that out of the way - let's go!
Step 1: Buy a custom domain
First things first - choose a domain name and a registrar. I chose GoDaddy as my domain provider because I wanted a something.ai
domain. This was unfortunately unavailable for purchase in AWS Route53. I would recommend checking in Route53 before you go with an external domain registrar as it will make things simpler.
For the rest of this guide, we'll be using the hugoexample.com
domain1 to illustrate. Don't forget to replace this with your own custom domain!
Step 2: Set up an S3 bucket, configured for Public Access
If you don't already have one, set up an AWS Account (tutorial here). The rest of this guide assumes you have successfully done this. If you've already got an AWS account - log in! Nip back once you're ready to go on - we'll wait.
Back? Ok, let's move on.
Tasks |
---|
Bucket 1: → Create S3 Bucket named hugoexample.com → Set up as Static Website → Access level Public Access + Custom Bucket Policy → Files stored here |
Bucket 2: → Create S3 Bucket named www.hugoexample.com → Set up Static Website REDIRECT → The End |
Bucket 1: Domain
Head on over to AWS Console S3 and create your S3 bucket where you will store your website files. The process is pretty straightforward. Important things to keep in mind:
-
The name of the bucket must be identical to your purchased domain. (so
hugoexample.com
in this example) -
Ensure that the bucket has public access by unchecking the appropriate box during creation
-
After the bucket is successfully created
-
Go to
Properties
and set it toStatic Web Hosting
. Type in the defaults for index and error pages -
Go to
Permissions
and ensure thatBlock Public Access
isOff
. Then type in the following bucket policy (substituting for your own S3 created bucket)1 2 3 4 5 6 7 8 9 10 11 12
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::hugoexample.com" } ] }
-
-
Bucket 2: SubDomain
Create another bucket and name it with the www.<apexdomain>
→ www.hugoexample.com
for this guide.
-
Go to
Properties
and set itStatic Web Hosting
, but choose theredirect to other website
option.-
Fill in your
domain
bucket name (hugoexample.com
) as the redirect target
-
This step ensures that both hugoexample.com and www.hugoexample.com show your website contents (without storing 2 parallel copies in both buckets. That would be silly)
Step 3: Create a simple Hugo Website
The Hugo website has excellent documentation, so for any issues in this section - just refer to the official docs at Hugo Quick Start Guide
Tasks |
---|
Install Hugo → Use Hugo to create new website directory → Hugo Build the site |
Pop the following commands into your terminal window:
|
|
That's it - your new website has been generated! Now we need to copy these files to our S3 bucket created earlier
Step 4: Install AWS CLI
Tasks |
---|
Install AWS CLI → Set up IAM Roles → Run aws configure |
You could upload your website to the S3 bucket via the web interface if you wished. But you will likely be spending a LOT of time tweaking and tuning your website, and uploading manually just becomes cumbersome. Hugo manages all the heavy lifting of doing this via a single command - so why wouldn't we set it up?
But first, we need to install the AWS CLI. Navigate to → Installing AWS CLIv2, select your OS and install the tool.
In order to complete the aws configure
step, you'll need to have an IAM
role with S3 bucket access set up. Follow this guide → AWS CLI Configuration Guide and note down the IAM IDENTITY
and IAM SECRET
Once you have these, run aws configure
on your local machine.
Step 5: Configure your Hugo deployment to upload to S3
Time to set up your Hugo deployment. Open up your config.toml
file (should be in your root website directory: ~/hugoexample.com/config.toml
directory) and add the following section to the bottom:
|
|
Once this is done, running hugo deploy
from the command line will upload your public files to the S3 bucket. (Note: hugo deploy chooses the first of the deployment targets without any arguments. Use hugo deploy --target=<target name>
if you'd like to be specific, or have multiple deployment targets)
Visit your S3 bucket's end-point (which should be something like http://www.hugoexample.com.s3-website-ap-southeast-1.amazonaws.com
) to validate that your site has been uploaded and all's working well.
Step 6: Set up Route53
Now we get to the tricksy bits. This step has quite a few moving parts, so do try to check your configurations before proceeding to the next stage.
Stage 1: Set up Route53 |
---|
Go to AWS Route53 → Set up a hosted zone → Point domain to S3 Endpoint |
Stage 2: Update Godaddy NameServers |
---|
Update Godaddy Nameservers with Route53 Nameservers → Wait for DNS Updates to propagate |
Stage 1: Set up Route53
Navigate to the Route53 service from your AWS Console: Route53 AWS Console
-
Create a hosted zone on Route53 and enter the
domain name
(without the www) that you purchased earlier. In our case, we'll go withhugoexample.com
. Leave it as aPublic Hosted Zone
and create it. -
Navigate to the
hugoexample.com
zone from the dashboard and you should see a few entries. Note thetype
. You should see an entry forNS
and one of typeSOA
.
Now it's time to create the record that will point your domain to the S3 bucket.
-
Click on
Create Record Set
→ leave theName:
field blank and ensure the type isA - IPv4 address
. -
Then check the
yes
button forAlias
. This will let your choose the Alias target from a dropdown menu.-
If you have set up your S3 bucket naming properly, you will be able to select it from the menu.
-
-
Click
Save Record
Stage 2: Update Godaddy Nameservers
If you bought your domain via Route53, skip this step. Otherwise:
-
Log in to godaddy and click on your purchased domain
-
Click on
manage DNS
andchange nameservers
-
Select
use your own
and enter all theRoute53
nameservers as individual entries.-
Note that you will have to remove the last
.
in your Route53 entries (those are used by AWS to denote the end of the domain)
-
-
Save
your changes.Brew a coffee, clear your browser history and flush dns cache. These updates will likely take up to a few hours (depending on various factors) to propagate.
Note: If you don't wish to set up https access, you can stop here. Wait for a few hours for the DNS changes to propagate and your site will be accessible.
Step 7: Set up HTTPS connections (Optional)
Tasks |
---|
Get a free SSL Certificate from AWS Certificate Manager → Set up a Cloudfront distribution → await activation → Redirect Route53 domain entry |
SSL Certificates can be quite expensive. The good news is that AWS provides a free SSL certificate for your cloudfront/Route53 services (auto-renew). So let's go ahead and grab one.
Important Make sure your region is US East (N. Virginia) region for the Certificate import
-
Log in to your AWS Console and navigate to
AWS Certificate Manager
(link) -
Request a Certificate
→Request a public certificate
-
Add both
hugoexample.com
andwww.hugoexample.com
to the domain names -
Choose
DNS Validation
(it's much easier if you've completed route53 setup) and proceed toconfirm and request
-
Then click the
Create Record in Route53
button (it should be available if you've set everything correctly so far) -
Done.
With that out of the way, it's time to create a Cloudfront distribution. Route53 and S3 don't enable direct HTTPS access to your buckets, so we'll have to create a Cloudfront distribution to do this. The good news, Cloudfront is AWS' global Content Delivery Network - which means it will cache your website at various locations around the world leading to speedy loading times to serve your avid, impatient, global userbase. But we're getting ahead of ourselves.
First:
-
Navigate to the AWS Cloudfront resource on your AWS Console (link)
-
Click on
Create Distribution
→Web
→Get Started
-
You're on a page with many many fields and you have immediately,but naturally, panicked. It's ok - we'll get through this together. Only a few fields need modification.
-
Origin Domain Name
- Don't choose the S3 bucket from the dropdown. Instead manually copy the endpoint url from your S3 bucket properties omitting the initial s3://. Should look something likehugoexample.com.s3.amazonaws.com
-
Origin Path
- Set to/
-
Origin ID
- will probably autofill. If not, use a name likeS3-hugoexample.com
-
Viewer Protocol Policy
- Redirect HTTP to HTTPS -
Compress Objects Automatically
- Yes -
Alternate Domain Names
- Enter bothhugoexample.com
andwww.hugoexample.com
in separate lines inside the textbox -
SSL Certificate
→ Custom SSL Certficate → Request or Import a Certificate with ACM → select the SSL cert you created earlier from the dropdown menu -
Create Distribution
We're nearly there! Wait for a short while until the distribution status is Enabled
.
Important: Access the cloudfront endpoint directly (This will look like
xxx114sxx.cloudfront.net
). If your site loads up - it's been configured properly. Do NOT proceed until your cloudfront url loads up your website
Now, update your Route53 DNS settings so that the whole world can access your website securely.
-
Go to your Route53 hosting zone for
hugoexample.com
and edit the domainA
entry that was pointed to your S3 bucket. -
Change it to your Cloudfront domain name, which should be something like
*.cloudfront.net
. You should be able to choose this from the dropdown menu. -
Also add a new
A
entry forwww.hugoexample.com
and do the same
Note: Once your DNS settings are properly set up, you can go ahead and delete your
www.hugoexample.com
S3 Bucket. We no longer need it for the aliasing of thewww
subdomain.
Huzzah - You're done!
That's it! Now wait a few hours for the DNS entries to propagate. Pat yourself on the back for a job well done. This is a good time to start customising your hugo blog (on your local machine).
Do leave a comment if you were able to set up your site using this guide (or if you found any errors)
Useful Tips
-
Use whatismydns to check how your DNS is propagating (if you are impatient like me!)
-
Flush your dns on MacOS (Catalina++) using
sudo killall -HUP mDNSResponder
-
After you update your godaddy nameservers, sometimes your
manage dns
page doesn't load. If this happens, open a new private mode window and log in there. Also, clearing your history can do the trick. -
After setting up or changing some configuration settings, click the raw S3 and Cloudfront endpoints to check that your website is loading up correctly.
-
While configuring your website, you may want to set your Nameserver TTL to something short (~5 minutes). Once you're certain that your DNS settings are properly configured, feel free to increase the TTL back up to a day or so.
-
After setting up cloudfront, try to resist uploading any customisations to your S3 buckets while the DNS entries are stabilising. Cloudfront caches your website assets by default for around 24 hours. You can manually invalidate for free only a limited number of times.
Other Resources
Ghost
Some useful resources on using Ghost
Hugo
Also a special shout out to David Baumgold's excellent and comprehensive tutorial that I used when I set my blog up → Link to David Baumgold - Host a Static Site on AWS, using S3 and CloudFront
1The website name without any identifiers is usually called the apex domain
. The website name with a www
appended (or other modifiers) to it is usually referred to the subdomain
. Bear this in mind if you're referring to guides/documentation