Hugo And AWS
Let’s generate a website with Hugo and deploy it using Amazon Web Services (AWS).
As an exercise we’ll walk through the following steps to deploy a simple static website:
- Generate a static website with Hugo.
- Create an S3 bucket and configure for public website access.
- Deploy the website to the S3 bucket.
- Configure a Route53 domain to point to the S3 bucket.
Tools and Methods
Hugo is a static website framework built in Go, it provides a convenient templating system that is then rendered to HTML and packaged along with CSS and other web resources to create a static website. I’m admittedly not an expert in using Hugo and will not go into much detail on it in this post.
AWS is an extensive suite of services provided by Amazon. We will only be scratching a very tiny portion of the services they provide but I would suggest S3 to be a service that everyone be comfortable with. Along with the CLI S3 provides an easy way to backup data - everything from production databases to personal documents.
Methods
Hugo - Create A Website
Checkout the official quick-start and walk through the initial steps to create a project. After spending several hours testing different themes that you’re not quite 100% happy with come back here.
To track our steps let’s create a Makefile in the project with the following dev
and dist
targets:
.PHONY: dist
dev:
hugo server --buildDrafts
dist:
hugo
make dev
- Runs a development server locally which will auto-reload when changes are made for easier development.
make dist
- Packages the website into the directory specified by the publishDir variable in Hugo’s config.yaml or config.toml file:
> grep publishDir ./config.yaml
publishDir: "dist"
S3 - Create And Configure A Bucket
For this step it’s assumed that the AWS CLI is installed and configured locally:
> aws configure
AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [us-west-2]:
Default output format [json]:
If not you will need to follow instructions online to create keys in IAM. For the purposed of this post you will also need the following permission policies:
- AmazonS3FullAccess
- AmazonRoute53FullAccess
To simplify the process of creating and configuring the S3 bucket I’ve created the following script s3-manage-website.sh.
Which we can integrate into our project by adding the core-devops repository as a subtree:
git subtree add --prefix .core-devops git@gitlab.com:mega-mac-slice/core-devops.git master --squash
And then modifying our Makefile by adding the following setup
target:
.PHONY: dist setup
BUCKET := example.org
REGION := us-west-2
dev:
hugo server --buildDrafts
dist:
hugo
setup:
.core-devops/scripts/aws/s3-manage-website.sh create $(BUCKET) $(REGION) \
&& .core-devops/scripts/aws/s3-manage-website.sh update $(BUCKET)
Note that we defined a variable REGION
at the top, this value can be determined by running aws configure get region
.
And run make setup
once before deploying to create and configure the S3 bucket.
Deploying
Modify your Makefile by adding the following deploy
, publish
and open
targets:
.PHONY: dist setup
BUCKET := example.org
REGION := us-west-2
dev:
hugo server --buildDrafts
dist:
hugo
setup:
.core-devops/scripts/aws/s3-manage-website.sh create $(BUCKET) $(REGION) \
&& .core-devops/scripts/aws/s3-manage-website.sh update $(BUCKET)
deploy:
aws s3 sync dist/ s3://$(BUCKET)
publish: dist deploy
open:
open $(shell .core-devops/scripts/aws/s3-manage-website.sh url $(BUCKET))
Now run make publish && make open
and your browser should be opened to something like http://example.org.s3-website-us-west-2.amazonaws.com
with your beautiful website visible to the world.
Route53 - Link Domain
Now that we have our site hosted in S3 let’s link it to a prettier domain. I’m going to omit the codifying of acquiring the domain as I don’t believe I have the control to not purchase a domain for every terrible idea I have, so we’ll assume the domain has been acquired through the AWS Console already.
To simplify the process of configuring the domain I’ve again created another script route53-manage-domain.sh.
Since we’ve already added the core-devops repo to our project we only need to update our Makefile with the link
target:
.PHONY: dist test clean
BUCKET := example.org
REGION := us-west-2
dev:
hugo server --buildDrafts
dist:
hugo
setup:
.core-devops/scripts/aws/s3-manage-website.sh create $(BUCKET) $(REGION) \
&& .core-devops/scripts/aws/s3-manage-website.sh update $(BUCKET)
deploy:
aws s3 sync dist/ s3://$(BUCKET)
publish: dist deploy
open:
open http://$(shell .core-devops/scripts/aws/s3-manage-website.sh url $(BUCKET) $(REGION))
link:
.core-devops/scripts/aws/route53-manage-domain.sh link $(BUCKET) $(REGION)
Afterwards we can run make link
, and provided there’s no error we can go for a walk and come back to a working domain. (The effects may not be immediate. A 5 to 20 minute walk should be sufficient.)
Results
mega-mac.com was created with Hugo and deployed with AWS, and this post is the resulting notes.
Discussion
Hugo isn’t the only static site generator, GatsbyJS seems pretty common in addition to just a few other ones in a variety of languages. The use of static generators is a component of the JAMstack.
A yeoman generator based off the findings from this post can be found at generator-hugo.
Future Considerations
AWS
- CloudFront - Configure a Content Delivery Network (CDN).
- Certificate Manager - Configure SSL.
Gitlab
- Setup Continuous Integration (CI) and Continuous Deployment (CD).
Website
- Contact Form.
- Google Analytics.
- SEO.