Deploying a Production Ready Hugo Site With 2 Lines of Code to AWS
A site hosted on AWS S3, using a custom domain, with a CDN and a SSL certificate.
I use the CDK, a custom construct, and Python to easily deploy this site to AWS.
- Install the AWS CDK
- Python 3.6+
- Your hugo website
- An AWS account and have previously setup the AWS CLI and run
aws configure
- A Route53 hosted zone and an available domain/subdoman A record (a domain or sub domain not currently in use)
Create a new directory and start a new CDK app:
mkdir cdk-app
cd cdk-app
cdk init --language python
This will generate a number of files, but the two that you care about are:
app.py
cdk_app/cdk_app_stack.py
open the cdk_app_stack.py
and add the following code at the bottom of the __init__
:
zone = HostedZone.from_lookup(
self, "HostedZone",
domain_name="MYDOMAINNAME.COM",
private_zone=False
)
StaticWebsite(
self, "serverlesslink-website",
hosted_zone=zone,
site_domain="BLOG.DOMAINNAME.COM",
sources="../public",
website_error="404.html"
)
In the first line, you will be creating a hosted zone object from a lookup, this is an existing hosted zone in Route53 and you must have access to use it.
The second line is the static website construct and it takes:
- The hosted zone you created above
- The site domain/subdomain you want to use for your hugo site
- The location of your code relative to the CDK app directory
- Optional, the error page if is not called
error.html
All that is left now is to deploy the site:
cdk deploy
Now that your infrastructure is in place, all you need to do moving forward is to sync the public directory with your website bucket.
Use a script like this to sync all your data and invalidate CloudFront
#!/bin/bash
# sync.sh
hugo -D
aws s3 sync public s3://BLOG.DOMAINNAME.COM
aws cloudfront create-invalidation --distribution-id YOURDISTRIBUTIONID --paths "/*"
It will take a few minutes to see all your updates.
While working with the CDK I learned some important lessons:
For local development and deployment, it is best to pass a custom env
to the application stack. Open the
app.py
and pass a custom env
dict to the stack:
import os
from aws_cdk import core
env = core.Environment(account=os.getenv('CDK_DEFAULT_ACCOUNT'), region=os.getenv('CDK_DEFAULT_REGION'))
CdkAppStack(app, "cdk-app", env=env)
All this is saying is that if the app can’t find some custom environment variables AWS_ACCOUNT_ID
and AWS_DEFAULT_REGION
, to use the CDK values which come from the
aws cli profile. You would use the custom env vars when deploying this in a CICD.
Simply follow the instructions in this post. I’ll try to fix this in the construct, but as of right now, you may need to do it manually.