Skip to main content

Command Palette

Search for a command to run...

Automating Static Website Deployment to S3 and CloudFront Using GitHub Actions (CI/CD)

Automate static website deployments on AWS using GitHub Actions, Amazon S3, and CloudFront

Published
4 min read
L

I build and deploy cloud-native applications using AWS and DevOps practices. I share practical tutorials on CI/CD pipelines, serverless architectures, and real project learnings, and I’m exploring MLOps.

Introduction

After setting up static website hosting using Amazon S3 and CloudFront, the next logical step is automation.

Manually uploading files to S3 every time you make a change is not scalable and does not reflect real-world DevOps practices. In production environments, deployments are automated using CI/CD pipelines to ensure speed, consistency, and reliability.

In this blog, we will build a CI/CD pipeline using GitHub Actions to automatically deploy a static website to Amazon S3 and invalidate the CloudFront cache whenever code is pushed to the repository.

Note: CloudFront invalidation removes cached objects from CloudFront edge locations so users receive the latest version of the content immediately after deployment.

This blog continues from:

  • Blog-1: CI/CD Basics with GitHub Actions

  • Blog-2: Hosting a Static Website Using Private S3 + CloudFront

What You Will Learn

In this blog, you will learn:

  • Why CI/CD is important even for static websites

  • How GitHub Actions works for automated deployments

  • How to deploy static files to Amazon S3 automatically

  • How to invalidate CloudFront cache after deployment

  • A real-world CI/CD architecture used in production

Why CI/CD for Static Websites?

Even though static websites are simple, deployment should never be manual in production.

Problems with Manual Deployment

  • Time-consuming uploads

  • High chance of human error

  • No consistency between deployments

  • Not suitable for production environments

Benefits of CI/CD

  • Automatic deployments on every code change

  • Faster and more reliable releases

  • Repeatable and consistent process

  • Aligns with real DevOps and SRE workflows

CI/CD Architecture Overview

Flow Explanation

  1. Developer pushes code to GitHub

  2. GitHub Actions workflow is triggered

  3. Static files are synced to the S3 bucket

  4. CloudFront cache is invalidated

  5. Updated content is served globally

This ensures every deployment is automated and instantly available worldwide.

Prerequisites

Before starting, ensure you have:

  • A GitHub repository with static website files (HTML, CSS, JavaScript)

  • A private Amazon S3 bucket for static website hosting

  • An Amazon CloudFront distribution connected to the S3 bucket

  • An IAM user with programmatic access

  • AWS credentials (Access Key ID and Secret Access Key)

    The S3 bucket and CloudFront distribution are assumed to be already configured as explained in Blog-2. and IAM User & Policy Setup Guide GitHub link https://github.com/nlokeshbabu1/AWS-S3.git

Step 1: Store AWS Credentials in GitHub Secrets

Never hardcode AWS credentials in your repository.

Steps

  1. Go to your GitHub repository

  2. Click Settings → Secrets and variables → Actions

  1. Click New repository secret

  2. Add the following secrets:

AWS_ACCESS_KEY_ID
AWS_SECRET_ACCESS_KEY
AWS_REGION
S3_BUCKET_NAME
CLOUDFRONT_DISTRIBUTION_ID

These secrets are securely encrypted and used by GitHub Actions during runtime.


Step 2: Create GitHub Actions Workflow

Create the following file in your repository:

.github/workflows/deploy.yml

GitHub Actions Workflow

name: Deploy Static Website to S3 and CloudFront

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

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

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Sync Files to S3
        run: |
          aws s3 sync . s3://${{ secrets.S3_BUCKET_NAME }} \
                        --delete \
                        --exclude ".git/*" \
                        --exclude ".github/*" \
                        --exclude "README.md" \
                        --exclude "LICENSE"


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

Workflow Explanation

Trigger

  • Runs automatically when code is pushed to the main branch

Checkout

  • Downloads repository code into the GitHub Actions runner

AWS Credentials

  • Authenticates securely using GitHub Secrets

S3 Sync

  • Uploads updated files to S3

  • Deletes removed files to maintain consistency

CloudFront Invalidation

  • Clears cached content

  • Ensures users see the latest version immediately


Deployment Result

Once the workflow completes successfully:

  • Static files are updated in S3

  • CloudFront serves the latest content

  • Website updates are live globally 🌍

No manual deployment steps are required.


Production Best Practices

  • Keep the S3 bucket private

  • Use CloudFront with Origin Access Control (OAC)

  • Store secrets securely in GitHub Secrets

  • Automate every deployment using CI/CD

  • Invalidate CloudFront cache only when required

This setup reflects how static websites are deployed in real-world production environments.


Conclusion

By combining Amazon S3, CloudFront, and GitHub Actions, we create a fully automated, secure, and scalable deployment pipeline for static websites.

This CI/CD setup:

  • Eliminates manual deployments

  • Improves reliability and speed

  • Follows DevOps and SRE best practices

This architecture is widely used across startups and enterprises for frontend and static website deployments.