Hugo with AWS cloudfront and s3 hosting with auto deploy from Github actions


Assuming you have a github repo for your nice hugo website. Including figuring out how to detach your theme from your repo.

Create

  • S3 bucket
  • Cloudfront distribution
  • Cloudfront origin towards S3 (with read-access via identity)

Then create

  • A IAM user with a policy that allows s3::PutObject and s3::PutObjectAcl in your s3 bucket.

IAM Policy

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "VisualEditor0",
                "Effect": "Allow",
                "Action": [
                    "s3:GetObjectAcl",
                    "s3:DeleteObject",
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:ListBucket",
                    "s3:PutObjectAcl",
                    "s3:GetBucketAcl"
                ],
                "Resource": [
                    "arn:aws:s3:::your-s3-bucket/*",
                    "arn:aws:s3:::your-s3-bucket"
                ]
            },
            {
                "Sid": "VisualEditor1",
                "Effect": "Allow",
                "Action": [
                    "s3:GetAccountPublicAccessBlock",
                    "s3:ListAllMyBuckets",
                    "s3:HeadBucket"
                ],
                "Resource": "*"
            }
        ]
    }

Create and copy the Access Token for the user, add this to the secrets needed for the GitHub action.

main.yml for github actions

name: publish to s3

on:
  push:
    branches:
    - master

jobs:
  build-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@master

    - name: build
      uses: docker://peaceiris/gha-hugo:v0.58.1
      with:
        args: --gc --minify --environment production

    - name: deploy to s3
      uses: olanystrom/s3-sync-action@master
      with:	
        args: --acl public-read
      env:
        SOURCE_DIR: './public'
        AWS_REGION: 'eu-north-1'
        AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

To get the index.html to work with subdirectories you need to rewrite directories destinations automatically, so I added a edgeLambda for that. Remember that you need to apply the lambda in us-east-1 so that cloudfront can use it.

https://serverlessrepo.aws.amazon.com/applications/arn:aws:serverlessrepo:us-east-1:621073008195:applications~standard-redirects-for-cloudfront

Installation via the Serverless Application Repository
Install the application “standard-redirects-for-cloudfront”.
Go to the Cloudformation Console
Select the created role (which brings you to the IAM console)
edit the trust relationship, set the policy to:

    {
    "Version": "2012-10-17",
    "Statement": [
        {
        "Effect": "Allow",
        "Principal": {
            "Service": [
            "lambda.amazonaws.com",
            "edgelambda.amazonaws.com"
            ]
        },
        "Action": "sts:AssumeRole"
        }
    ]
    }
Then, go back to Cloudformation console

  1. Select the Output Value, this is the ARN (including the version) for the Lambda function.
  2. In CloudFront edit a Behaviour and add a Lambda Function Association with the Event Type “Origin Request” and enter the Lambda function ARN from the previous step.
  3. Wait for the CloudFront distribution to deploy.