Create S3 deployment pipeline for Hugo with GitHub Actions

S3 deployment pipeline for Hugo with GitHub Actions

In this post I would like to describe how to create a simple Continuous Deployment pipeline for Hugo website with GitHub Actions.

AWS GitHub account

First of all, we will need a AWS access key & secret key for GitHub Actions pipeline user to be able to deploy the website. I will create it with Terraform. The user github_deploy is created with aws_iam_user resource, you can of course changed the name of the user. I am also creating a policy aws_iam_policy_document to access S3 bucket with the website. I am assigning user with policy with aws_iam_user_policy. The access key is created with aws_iam_access_key . The key can be access by output value aws_iam_deploy_secret.

data "aws_iam_policy_document" "github_deploy" {
  statement {
    actions = [

    resources = [
  statement {
    actions = [
    resources = [

resource "aws_iam_user" "github_deploy" {
  name = "github_deploy"

resource "aws_iam_user_policy" "github_deploy" {
  name   = "deploy_policy"
  user   =
  policy = data.aws_iam_policy_document.github_deploy.json

resource "aws_iam_access_key" "github_deploy" {
  user =

output "aws_iam_deploy_secret" {
  value     = aws_iam_access_key.github_deploy
  sensitive = true

To create our resources we run terraform apply and to see the keys we can check them with terraform output aws_iam_deploy_secret.

❯ terraform apply

aws_iam_deploy_secret = <sensitive>
❯ terraform output aws_iam_deploy_secret
  "encrypted_secret" = tostring(null)
  "id" = "AKXXX"
  "key_fingerprint" = tostring(null)
  "pgp_key" = tostring(null)
  "secret" = "XXX"
  "ses_smtp_password_v4" = "BAXXX"
  "status" = "Active"
  "user" = "github_deploy"

Hugo S3 Deploy

Hugo supports deploying to S3 out-of-the-box. To do it, just add following to config.toml.

# By default, files are uploaded in an arbitrary order.
# Files that match the regular expressions in the "Order" list
# will be uploaded first, in the listed order.
order = [".jpg$", ".gif$"]

# An arbitrary name for this target.
name = "prod"

# S3; see
# For S3-compatible endpoints, see
URL = "s3://"

# Cache static assets for 1 year.
pattern = "^.+\\.(js|css|svg|ttf)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = true

pattern = "^.+\\.(png|jpg)$"
cacheControl = "max-age=31536000, no-transform, public"
gzip = false

# Set custom content type for /sitemap.xml
pattern = "^sitemap\\.xml$"
contentType = "application/xml"
gzip = true

pattern = "^.+\\.(html|xml|json)$"
gzip = true

GitHub Actions

To setup the pipeline we need to do two things:

  1. Add secrets to repository settings.
  2. Add workflow file and commit to the repo.

AWS secrets

  1. Go to your repo in GitHub
  2. Go to Settings -> Secrets
  3. Click New repository secret
  5. The values you should grab from terraform output aws_iam_deploy_secret from fields id and secret.

GitHub Actions AWS secrets

Workflow file

Now we should create file .github/workflows/main.yml describing the pipeline.

name: Hugo S3 deploy

      - master

    runs-on: ubuntu-20.04
      group: ${{ github.workflow }}-${{ github.ref }}
      - uses: actions/checkout@v2
          submodules: true  # Fetch Hugo themes (true OR recursive)
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: eu-central-1

      - name: Setup Hugo
        uses: peaceiris/actions-hugo@v2
          hugo-version: '0.87.0'
          # extended: true

      - name: Build HTML public/
        run: hugo --minify

      - name: Deploy to S3 bucket
        run: hugo deploy


After you commit this file to the repository, the pipeline should start automatically. You can see it by clicking Actions tab in GitHub repository.

Also what I noticed, the Hugo deployment is way faster comparing to Gatsby (10 s vs 2 minutes).

GitHub Actions Workflows GitHub Actions S3 Hugo deployment

Join the Newsletter

Subscribe to get my latest content by email.

    I won't send you spam. Unsubscribe at any time.

    For comments, please send me 📧 an email