Github Actions, Hugo Deploy and Amazon S3

This blog post is part of a series called How this blog is made.

In this post we will use Github Actions to automatically deploy all changes in our Github master branch to our S3 bucket. To authorize Github to perform this action we have to create an AWS Access Key. For security reasons this AWS Access Key will be linked to a AWS User with only the necessary permissions to perform this action.

We will be focusing on this part of the diagram:

Diagram

AWS Identity and Access Management (IAM)#

  1. Go to your AWS Console and to IAM.
  1. On the left side to Policies and click Create policy:
    1. Select JSON.
    2. Copy and paste:
    {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Sid": "GithubActionsWebsite",
             "Effect": "Allow",
             "Action": [
                 "s3:ListBucket",
                 "s3:GetObject",
                 "s3:PutObject",
                 "s3:DeleteObject",
                 "cloudfront:CreateInvalidation"
             ],
             "Resource": [
                 "arn:aws:s3:::<Your-Bucket-Name>",
                 "arn:aws:s3:::<Your-Bucket-Name>/*",
                 "<CF-Distribution-ARN>"
             ]
         }
     ]
     }
    
    1. Click Review policy.
    2. Choose a name like DeployWebsite.
    3. Click Create policy.
  1. On the left side to Users and click Add user:
    1. Choose a name like github-action-website.
    2. Allow Programmatic access.
    3. Click Next: Permissions.
    4. Choose Attach existing policies directly and in the list choose DeployWebsite.
    5. Click Next: Tags.
    6. Tag your user. I go with Key = project and Value = a-h.io.
    7. Click Next: Review.
    8. Click Create user.
    9. Save both the <Access-key-ID> and the <Secret-access-key> for later.

Now we have created a User with an Access Key with the permissions to change our website on <Your-Bucket-Name> and can create an invalidation of files at <CF-Distribution-ARN>.

Hugo Deploy#

Hugo makes it easy to deploy your website to Amazon S3 and to access your Cloudfront distribution.

  1. Add this to your config.toml:
    [deployment]
    
    [[deployment.targets]]
    name = "Website <Your-Domain>"
    URL = "s3://<Your-Bucket-Name>?region=<Your-Region>"
    
    cloudFrontDistributionID = "<CF-Distribution-ID>"
    
    [[deployment.matchers]]
    # Cache static assets for 20 years.
    pattern = "^.+\\.(js|css|svg|ttf|woff|woff2|eot|png|jpg|gif|svg|ttf)$"
    cacheControl = "max-age=630720000, no-transform, public"
    gzip = true
    
    [[deployment.matchers]]
    pattern = "^.+\\.(html|xml|json)$"
    gzip = true
    
  2. Install the AWS CLI
  3. Configure the AWS CLI with your <Access-key-ID>, <Secret-access-key> and <Your-Region>
  4. Test your configuration with:
    # delete the public folder
    rm -rf public
    # build the website
    hugo --minify
    # deploy the website to AWS and invalidate the Cloudfront cache
    hugo deploy --maxDeletes -1 --invalidateCDN
    

You should see Success.

Github Actions#

To automate this workflow we will use Github Actions.

  1. Create a new Github workflow config file:
    mkdir -p .github/workflows/
    touch .github/workflows/main.yml
    
  1. Copy and paste to main.yml:

    name: Deploy website to S3 bucket
    
    on:
      push:
        branches:
          - master
    
    jobs:
      deploy:
        runs-on: ubuntu-18.04
        steps:
          - uses: actions/checkout@v2
            with:
              submodules: true  # Fetch Hugo themes 
              fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod
    
          - name: Setup Hugo
            uses: peaceiris/actions-hugo@v2
            with:
              hugo-version: 'latest'
              extended: true
    
          - name: Configure AWS Credentials
            uses: aws-actions/configure-aws-credentials@v1
            with:
              aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
              aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
              aws-region: ~Your-Region~
    
          - name: Build website
            run: hugo --minify
    
          - name: Hugo deploy static site to S3 bucket and invalidate Cloudfront cache
            run: hugo deploy --maxDeletes -1 --invalidateCDN
    

    Do not forget to fill in <Your-Region>. Do not fill in your <Access-key-ID> or <Secret-access-key>. Secret keys like AWS Credentials should not be in code, but in a secure section of your repository.

  2. Go to <Your-Repository> on github.com, here to Settings and to Secrets:

    1. Click New secret.
    2. Name = AWS_ACCESS_KEY_ID and Value is your <Access-key-ID>.
    3. And another secret. Click New secret.
    4. Name = AWS_SECRET_ACCESS_KEY and Value is your <Secret-access-key>.

Now every time you push changes to your master branch Github Actions will deploy those changes to your website.