Automate Secure AWS S3 & CloudFront Deployments with GitHub Actions

Aug 25, 2025 by schufeli - 4 min read

Introduction

In my previous post, I showed how to cheaply and securely host a static website on AWS using an S3 bucket and CloudFront CDN. Now, let’s automate deployments using GitHub Actions with AWS IAM role assumption, a best practice approach that avoids managing long-lived AWS credentials and increases deployment security.

This guide will walk you through configuring your GitHub repository and AWS account to build your site and deploy it automatically to your private S3 bucket behind CloudFront—using only official AWS GitHub Actions and CLI tools, with no third-party dependencies.

What You’ll Need

  • Your website hosted on AWS with S3 and CloudFront (refer to the previous tutorial for setup)
  • A GitHub repository containing your static site source code
  • AWS IAM permissions to create policies, roles, and identity providers
  • Familiarity with GitHub Actions workflows and AWS CLI

Creating a Policy

Start by creating an AWS IAM policy granting the minimum permissions necessary for deployment:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": [
        "cloudfront:CreateInvalidation",
        "cloudfront:GetDistribution",
        "cloudfront:GetDistributionConfig"
      ],
      "Resource": "arn:aws:cloudfront::your-account-id:distribution/your-distribution-id"
    }
  ]
}

Important:

  • Replace your-bucket-name with your actual S3 bucket name.
  • Replace your-account-id and your-distribution-id with your AWS account and CloudFront distribution IDs respectively.

Attach this policy to the IAM role you will create in the next step.


Add GitHub as an Identity Provider in AWS IAM

To allow GitHub Actions to assume an AWS role securely using OpenID Connect (OIDC), add GitHub as an identity provider:

  1. In the AWS Management Console, navigate to IAM > Identity Providers.
  2. Click Add provider.
  3. Set Provider type to OpenID Connect.
  4. Set the Provider URL to: https://token.actions.githubusercontent.com

Create an IAM Role for GitHub Actions

Create a role your GitHub workflow will assume:

  1. Go to IAM > Roles, then click Create role.
  2. Select Web identity as the trusted entity type.
  3. Choose the GitHub identity provider you created above.
  4. Set the audience to: sts.amazonaws.com
  5. Set the Github organization either to your account name can be extracted by the github url of your repository or the name of an organisation.
  6. Set the Github repository to the name of your respository
  7. Set the Github branch to the name of your branch
  8. Attach the policy you created earlier with minimal S3 and CloudFront permissions.
  9. Complete creating the role and note its ARN (you will need it in GitHub Secrets).

Configure GitHub Secrets

In your GitHub repository, navigate to Settings > Secrets and variables > Actions and add the following secrets:

  • AWS_REGION — your AWS region (e.g., eu-central-1)
  • ROLE_TO_ASSUME — the ARN of the IAM role created above
  • S3_BUCKET — your S3 bucket name
  • CLOUDFRONT_DISTRIBUTION_ID — your CloudFront distribution ID

You do not need to provide AWS access keys due to OIDC role assumption.


GitHub Actions Workflow Using Official AWS Action

Create or update .github/workflows/deploy.yml in your repository with this workflow configuration:

name: Build and Deploy to AWS

on:
  push:
    branches:
      - main

permissions:
  id-token: write
  contents: read

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: ${{ secrets.ROLE_TO_ASSUME }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '22.16.0' # Adjust Node.js version as needed

      - name: Install dependencies
        run: npm install

      - name: Build site
        run: npm run build

      - name: Sync site to S3
        run: aws s3 sync ./dist s3://${{ secrets.S3_BUCKET }} --delete

      - name: Invalidate CloudFront cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} --paths "/*"

Summary

By adding GitHub as an OIDC identity provider, creating a tightly scoped IAM policy and role for GitHub Actions, and using the official AWS GitHub Action and CLI, you can establish a secure, fully automated workflow to deploy your static website hosted in AWS S3 and delivered via CloudFront.

This method removes the risks of long-lived AWS credentials and leverages short-lived tokens with precise access control tied directly to your GitHub repository and branch.

Happy shipping! 🚀