Deploying Hugo with AWS CodeBuild on Lambda Compute
Introduction
In this recipe, we will review how to deploy a Hugo static site using AWS CodeBuild on AWS Lambda compute. AWS Lambda compute offers optimized start-up speeds and automatic scaling for faster builds. However, there are some limitations to consider.
We will use AWS CodeBuild to build the Hugo site, deploy it to an S3 bucket, and invalidate the CloudFront cache. GitHub will be used as the source repository for the Hugo site.
Pre-requisites
Before we start, make sure you have the following:
- your Hugo site source code on GitHub
- your Hugo site is already hosted on AWS S3 and CloudFront. If not, follow the Hosting Hugo on AWS S3 and CloudFront recipe to set it up.
Step 1: Create a new IAM role for CodeBuild project
We need to create a new IAM role that will be used by the CodeBuild project to sync
the S3 bucket and invalidate
CloudFront distribution.
Create a new policy
- Go to the AWS IAM console: Policies.
- Click on the
Create policy
button. - Click on the
JSON
tab and paste the following policy document:
YOUR_BUCKET_NAME
, YOUR_ACCOUNT_ID
, and YOUR_DISTRIBUTION_ID
with your values.{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetBucketAcl",
"s3:GetBucketLocation",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::YOUR_BUCKET_NAME",
"arn:aws:s3:::YOUR_BUCKET_NAME/*"
]
},
{
"Effect": "Allow",
"Action": [
"cloudfront:CreateInvalidation"
],
"Resource": [
"arn:aws:cloudfront::YOUR_ACCOUNT_ID:distribution/YOUR_DISTRIBUTION_ID"
]
}
]
}
- Click on the
Next
button. - Fill in the policy name and description.
- Click on the
Create policy
button.
Create a new role
- Go back to the AWS IAM console: Roles.
- Click on the
Create Role
button. - Select
AWS service
as the trusted entity. - Choose
CodeBuild
as the service that will use this role. - Click on the
Next: Add Permissions
button. - Search and check the checkbox next to the policy you created previously.
- Click on the
Next: Name, review and create
button. - Fill in the role name and description.
- Click on the
Create role
button.
Now you have a new IAM role that can be used by the CodeBuild project.
Step 2: Create a new CodeBuild project
Let’s create a new CodeBuild project that will build and deploy our site on every push to the GitHub repository.
Go to the AWS CodeBuild console and click on the Create build project
button.
Project configuration
- Fill in the project name and description.
- Restrict number of concurrent builds this project can start to
1
.
Source
- Select
GitHub
as the source provider. - Click on the
Connect to GitHub
button and authorize AWS to access your GitHub repositories. - Select your repository and branch.
Environment
- Select
Managed Image
as the environment image. - Choose
Lambda
as the compute type. - Operating system:
Amazon Linux
(you don’t have other options here). - Runtime:
Golang
. - Image:
aws/codebuild/amazonlinux-aarch64-lambda-standard:go1.21
or most recent. - Image version:
Always use the latest image for this runtime version
. - Service role:
Existing service role
. - Role ARN: choose the role you created in the previous step.
- Check the
Allow AWS CodeBuild to modify this service role so it can be used with this build project
checkbox.
Buildspec
Choose Insert build commands
and paste the following buildspec:
yum
or rpm
since they require root access. Therefore, we need to manually download and extract Hugo. For more information, refer to the Limitations of AWS Lambda compute.YOUR_BUCKET_NAME
, YOUR_REGION
, and YOUR_DISTRIBUTION_ID
with your values.version: 0.2
phases:
install:
commands:
# Download and extract Hugo
- curl -Ls https://github.com/gohugoio/hugo/releases/download/v0.127.0/hugo_extended_0.127.0_linux-arm64.tar.gz -o /tmp/hugo.tar.gz
- mkdir /tmp/hugo_0.127.0
- tar xf /tmp/hugo.tar.gz -C /tmp/hugo_0.127.0
- /tmp/hugo_0.127.0/hugo version
build:
commands:
# Build the site using Hugo
- /tmp/hugo_0.127.0/hugo --minify --gc
post_build:
commands:
# Sync the Hugo build public folder with S3 bucket
- aws s3 sync public/ s3://YOUR_BUCKET_NAME --region YOUR_REGION --delete
# Invalidate CloudFront cache
- aws cloudfront create-invalidation --distribution-id YOUR_DISTRIBUTION_ID --paths '/*'
Artifacts
Select No artifacts
as the output artifact type since we are deploying the site to S3 withing the buildspec.
Logs
Optionally, you can configure CloudWatch logs for the build project. This will help you debug the build process.
Step 3: Trigger the build
Now you can trigger the build by pushing a new commit to the GitHub repository. The CodeBuild project will automatically start the build process and deploy the site to the S3 bucket. Alternatively, you can manually start the build pressing the Start build
button in the CodeBuild console.
That’s it! You have successfully deployed your Hugo site using AWS CodeBuild on a Lambda environment.
CloudFormation deployment
If you prefer to deploy the CodeBuild project using CloudFormation, you can use the template below. It is parametrized with the required values.
AWSTemplateFormatVersion: '2010-09-09'
Description: CodeBuild project for Hugo site deployment
Parameters:
ProjectName:
Type: String
Description: CodeBuild project name
Default: HugoSiteBuild
SiteBucketName:
Type: String
Description: Site S3 bucket name
DistributionId:
Type: String
Description: CloudFront distribution ID
Region:
Type: String
Description: AWS region
HugoVersion:
Type: String
Description: Hugo version
Default: 0.127.0
GitHubRepo:
Type: String
Description: GitHub repository URL
Resources:
ServiceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: codebuild.amazonaws.com
Action: sts:AssumeRole
Policies:
- PolicyName: CodeBuildServiceRolePolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !Sub arn:aws:logs:${Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}
- !Sub arn:aws:logs:${Region}:${AWS::AccountId}:log-group:/aws/codebuild/${ProjectName}:*
- PolicyName: DeploySiteCodeBuildPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetObject
- s3:DeleteObject
- s3:GetBucketAcl
- s3:GetBucketLocation
- s3:ListBucket
Resource:
- !Sub arn:aws:s3:::${SiteBucketName}
- !Sub arn:aws:s3:::${SiteBucketName}/*
- Effect: Allow
Action:
- cloudfront:CreateInvalidation
Resource:
- !Sub arn:aws:cloudfront::${AWS::AccountId}:distribution/${DistributionId}
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
Description: Build and deploy Hugo site
ConcurrentBuildLimit: 1
Environment:
Type: ARM_LAMBDA_CONTAINER
ComputeType: BUILD_LAMBDA_1GB
Image: aws/codebuild/amazonlinux-aarch64-lambda-standard:go1.21
ServiceRole: !GetAtt ServiceRole.Arn
Source:
Type: GITHUB
BuildSpec: !Sub |
version: 0.2
phases:
install:
commands:
- curl -Ls https://github.com/gohugoio/hugo/releases/download/v${HugoVersion}/hugo_extended_${HugoVersion}_linux-arm64.tar.gz -o /tmp/hugo.tar.gz
- mkdir /tmp/hugo_${HugoVersion}
- tar xf /tmp/hugo.tar.gz -C /tmp/hugo_${HugoVersion}
- /tmp/hugo_${HugoVersion}/hugo version
build:
commands:
- /tmp/hugo_${HugoVersion}/hugo --minify --gc
post_build:
commands:
- aws s3 sync public/ s3://${SiteBucketName} --region us-east-1 --delete
- aws cloudfront create-invalidation --distribution-id ${DistributionId} --paths '/*'
Location: !Ref GitHubRepo
Artifacts:
Type: NO_ARTIFACTS
Triggers:
Webhook: true
BuildType: BUILD
FilterGroups:
- - Type: EVENT
Pattern: PUSH
LogsConfig:
CloudWatchLogs:
Status: ENABLED
GroupName: !Sub /aws/codebuild/${ProjectName}
Conclusion
In this recipe, we learned how to deploy a GitHub sourced Hugo static site using AWS CodeBuild on a Lambda environment which is a cost-effective, easier and faster way compared to the traditional EC2 environment. We also scripted all the steps in a CloudFormation template for easy deployment and management.