How to Deploy a Static Site to AWS S3 and CloudFront From CI
Sync the build to S3 with --delete, then invalidate CloudFront so the edge serves the new files.
Run aws s3 sync <dir> s3://<bucket> --delete to upload and prune, then aws cloudfront create-invalidation --paths "/*" to clear the edge cache. Prefer OIDC role assumption over long-lived keys.
Steps
- Configure AWS credentials, ideally via
aws-actions/configure-aws-credentialswith OIDC. - Sync the build directory to the bucket with
--delete. - Create a CloudFront invalidation for the changed paths.
- Wait for the invalidation only if a later step depends on it.
Workflow
.github/workflows/ci.yml
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
steps:
- uses: actions/checkout@v4
- run: npm ci && npm run build
- uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: arn:aws:iam::123456789012:role/deploy
aws-region: us-east-1
- run: aws s3 sync dist s3://my-site-bucket --delete
- run: >-
aws cloudfront create-invalidation
--distribution-id E123ABC --paths "/*"Gotchas
- Invalidating "/*" is billed after the first 1000 paths per month; scope paths when you can.
- The IAM role needs both s3:PutObject/DeleteObject and cloudfront:CreateInvalidation.
- Upload immutable fingerprinted assets first, then HTML, to avoid serving stale references.
Related guides
How to Set Cache Headers for Static Assets on DeploySet long immutable cache headers for fingerprinted static assets and a short or no-cache header for HTML so b…
How to Purge the CDN Cache After Deploying a Static SitePurge the CDN cache after a static site deploy so the edge stops serving the old build, using CloudFront inva…