jonelantha: Blog


How-To: Setup Gatsby on AWS using GitHub Actions [3/3]: Setup Continuous Deployment with GitHub Actions

14th April 2022 - (revised version of a post originally published 3rd March 2020)

This is Part 3 of a how-to guide to help you host your Gatsby site on AWS (with Continuous Deployment provided by GitHub Actions). See Part 1 and Part 2 for more information.

It's time to deploy your Gatsby Site!

We'll assume you have a Gatsby project ready to go and it's in a repo which has been pushed up to GitHub. If you've followed the previous parts of the guide you should also have an S3 bucket and CloudFront distribution waiting ready to host your site. Time to deploy!

There's two parts to setting up the deployment, first we need to create an AWS IAM user, GitHub will use this user to access S3 and CloudFront. After that we need to create the deployment workflow in GitHub - once that's done any changes pushed to the main branch (or master branch) will automatically be deployed to AWS.

Setup the IAM user

  1. In the AWS console go to the IAM section
  2. Click Policies in the left hand menu
  3. Click Create Policy
  4. On the Create Policy screen:
    • Click the JSON tab
    • Cut and paste the following:
    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Sid": "1",
                "Effect": "Allow",
                "Action": "s3:ListBucket",
                "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME"
            },
            {
                "Sid": "2",
                "Effect": "Allow",
                "Action": [
                    "s3:PutObject",
                    "s3:GetObject",
                    "s3:DeleteObject"
                ],
                "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            },
            {
                "Sid": "3",
                "Effect": "Allow",
                "Action": "cloudfront:CreateInvalidation",
                "Resource": "YOUR_CLOUDFRONT_ARN"
            }
        ]
    }
    • In the above, replace YOUR_BUCKET_NAME with your bucket name (you should replace both occurrences but be careful to leave the /* in place after the second occurrence)
    • Replace YOUR_CLOUDFRONT_ARN with the full ARN for your CloudFront distribution. This can be found on the summary page of your CloudFront distribution (see Part 1 for details). It should have the form arn:aws:cloudfront::############:distribution/##############
    • Click Next: Tags
      • If you're a tags user then you should add a tag, otherwise it's fine to leave this blank.
    • Click Next: Review
  5. On the Review policy screen:
    • Name: Enter a name for the new policy, something like GatsbyDeployPolicy
    • Description: Enter a description if you wish but it's fine to leave this blank
    • Summary: This should show that CloudFront has limited 'Write' access and that S3 has limited 'List', 'Read' and 'Write' access - perfect!
    • Click Create policy
  6. Back on the IAM dashboard, click Users in the left hand menu
  7. Click Add User
  8. On the Add User screen
    • User name: enter GatsbyDeploy
    • Access type: select Programmatic access
    • Click Next: Permissions
  9. On the Set permissions screen
    • Select Attach existing policies directly
    • In the search box enter GatsbyDeployPolicy (or whatever you named the policy above)
    • Select the checkbox on the GatsbyDeployPolicy row
    • Click Next: Tags
  10. On the Add tags screen:
    • Once again, if you're a tags user then you should add a tag, otherwise it's fine to leave this blank.
    • Click Next: Review
  11. On the Review screen:
    • Have a quick check to see if everything looks ok.
    • Click Create user
  12. On the Success screen:
    • Click Show on the Secret access key

    • We'll need these two keys to setup the GitHub Actions deployment workflow in the next section - so keep the console open in your browser until you've setup the secrets, we'll do that at the beginning of the next section.

      These two values grant access to modify the files in your bucket - so as a security best practice you should avoid saving these values anywhere permenantly

So what did we do in this section? We created a user which has some very specific permissions set (these were defined as part of the GatsbyDeployPolicy policy). These are the very minimum privileges needed to deploy the site (this is in accordance with AWS IAM best practices to grant the least privileges to users).

Setup the GitHub Actions deployment workflow

Finally it's time to setup the GitHub Actions deployment workflow.

  1. Login to GitHub and go to the repo for your Gatsby project
  2. Click the Settings tab
  3. In the left hand menu click Secrets
  4. Click New repository secret
    • Name: enter AWS_ACCESS_KEY_ID
    • Value: paste in the Access key ID value shown in the AWS console.
    • Click Add secret
  5. Again, click New repository secret to add a second secret:
    • Name: enter AWS_SECRET_ACCESS_KEY
    • Value: paste in the Secret access key value shown in the AWS console.
    • Again, click Add secret
  6. The secrets should now be added and there's no longer any reason to retain the two AWS access keys

Now open up your Gatsby project in your favourite IDE

  1. In the root of your folder create a .github directory (if it's not already there)
  2. Inside the .github directory create a workflows directory.
  3. Inside the workflows directory create a file called deploy.yml - it can be named anything but should end in .yml (so your new file should be located at ./.github/workflows/deploy.yml)
  4. Inside the new file paste in the following:
    name: Deploy
    on:
      push:
        branches:
          - main    # might be `master` for older repos
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - name: Checkout
            uses: actions/checkout@v2
          - name: Use Node.js
            uses: actions/setup-node@v1
            with:
              node-version: 16.x
          - name: Cache node modules
            uses: actions/cache@v1
            with:
              path: ~/.npm
              key: ${{ runner.os }}-node-${{ hashFiles('**/package-lock.json') }}
              restore-keys: ${{ runner.os }}-node-
          - name: Build
            run: |
              npm ci
              npm run build
          - 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_AWS_REGION
          - name: Deploy
            uses: jonelantha/gatsby-s3-action@v1
            with:
              dest-s3-bucket: YOUR_BUCKET_NAME
              cloudfront-id-to-invalidate: YOUR_CLOUDFRONT_ID
    You'll need to substitute the following values into the above:
    • Make sure the name of your main branch is correct - it will be main for newer repos and master for older repos
    • YOUR_BUCKET_NAME: just the S3 bucket name, not the full ARN
    • YOUR_CLOUDFRONT_ID: the 14 character CloudFront ID (example E1FFE74E8RVG6W). See Part 1 for details where to find this
    • YOUR_AWS_REGION: your region, for example eu-west-2
    NOTE: You may prefer not to add these values to the repo, particularly if it's a public repo. Instead you can define these values as secrets and then add the ${{ secrets.SECRET_NAME }} syntax to the workfile file in the appropriate locations.
  5. Commit this new file into main (or master) and it push up to GitHub (it's fine to create a Pull Request first and then review/merge). Once merged the deployment should begin.
  6. In GitHub take a look at the Actions tab, you should be able to see the console output as your site is deployed to AWS!
  7. Once complete, in your browser navigate to your CloudFront distribution's Domain name (it's on the CloudFront Distribution summary page, see Part 1 for more details). Fingers crossed you'll see your Gatsby site, served by AWS!

So what's going on in that deploy.yml file?

GitHub Actions will execute the workflow file step by step - this happens every time any changes are pushed up to the main (or master) branch on GitHub. Most steps should be straightforward but there's a couple which may need some further explanation:

  • Cache node modules - actions/cache@v1: this caches the node_modules directory between builds. Note it's only cached for a week so you'll need to be building reasonably frequently to see any benefit from this. See the GitHub Actions caching documentation for further details.

  • Deploy - jonelantha/gatsby-s3-action@v1: this is a GitHub action created by the author for the purpose of deploying a Gatsby site to AWS:

    • It copies the site files to the specified S3 bucket and then sets the cache headers according to Gatsby caching recommendations
    • It invalidates the specified CloudFront distribution - if we don't do this then Cloudfront may continue to serve up the previous version of your site.

    See the documentation if you're interested in learning more.

Next steps

Great, you did it! There's a couple of things you'll probably want to consider doing next:

That's it! Thanks for reading and good luck with your new Gatsby site!


© 2003-2023 jonelantha