Deploy a static website to AWS S3 with CloudFront CDN using Terraform and GitHub Actions.
- Creates an S3 bucket configured for static website hosting
- Sets up CloudFront distribution for fast global content delivery
- Automatically uploads your website files from the
www/directory - Includes CI/CD pipeline for automated deployments
- Terraform >= 1.4
- AWS account with appropriate permissions
- AWS CLI configured (
aws configure)
-
Clone and configure:
git clone <repository-url> cd s3_static_website cp terraform.tfvars.sample terraform.tfvars
-
Edit
terraform.tfvarswith your settings:aws_region = "us-east-1" bucket_prefix = "my-site-" aws_s3_bucket_versioning = "Enabled"
-
Update
backend.tfwith your state bucket:bucket = "your-terraform-state-bucket"
-
Deploy:
terraform init terraform plan terraform apply
-
Access your site using the CloudFront URL from the output.
├── .github/workflows/
│ ├── terraform.yml # CI/CD deployment pipeline
│ └── destroy.yml # Infrastructure teardown
├── www/ # Your website files go here
│ ├── index.html
│ ├── error.html
│ ├── style.css
│ └── script.js
├── s3.tf # S3 bucket configuration
├── cloudfront.tf # CloudFront distribution
├── variable.tf # Input variables
└── terraform.tfvars # Your values (gitignored)
-
Add GitHub Secrets in your repository settings:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY
-
Push to
mainbranch:git add . git commit -m "Deploy website" git push origin main
The GitHub Actions workflow automatically:
- Validates and formats Terraform code
- Plans infrastructure changes
- Applies changes on push to main
terraform applyWith GitHub Actions:
- Edit files in
www/directory - Commit and push to main branch
Manual:
- Edit files in
www/directory - Run
terraform apply
Terraform automatically detects and uploads only changed files.
| Variable | Description | Default |
|---|---|---|
aws_region |
AWS region | us-east-1 |
bucket_prefix |
S3 bucket name prefix | my-static-website- |
aws_s3_bucket_versioning |
Enable versioning | Enabled |
bucket_region |
S3 bucket region | us-east-1 |
tags |
Resource tags | See variable.tf |
After deployment, you'll get:
website_endpoint- Direct S3 website URLcdn_domain_name- CloudFront URL (recommended for production)
To remove all resources:
terraform destroyBucket name already exists: Change bucket_prefix to something unique.
CloudFront not showing updates: Wait for cache TTL (up to 24h) or create an invalidation:
aws cloudfront create-invalidation --distribution-id <ID> --paths "/*"GitHub Actions failing: Verify AWS secrets are correctly set and IAM permissions are sufficient.
- Never commit
terraform.tfvarsor AWS credentials - Store AWS credentials in GitHub Secrets for CI/CD
- The S3 bucket allows public read access (required for static websites)
- CloudFront provides HTTPS by default
See LICENSE file for details.