# Static Site Deployment on AWS S3 & CloudFront  A complete guide and template for deploying blazing-fast static websites on AWS infrastructure using S3 for storage and CloudFront as a global CDN. ## Features - High Performance: Global content delivery via CloudFront's CDN - Cost Effective: Pay only for what you use (often <$1/month for small sites) - Secure: Free SSL certificates via AWS Certificate Manager - Scalable: Automatically handles traffic spikes - Global Availability: 200+ edge locations worldwide ## Prerequisites - AWS account (Free tier eligible) - Static website files (HTML, CSS, JS, images) - Domain name (optional but recommended) - AWS CLI installed (optional but helpful) ## Step-by-Step Deployment Guide ### 1. Prepare Your Static Site Ensure your site works locally and all links are relative (not absolute). ```bash # Example structure your-site/ ├── index.html ├── css/ │ └── style.css ├── js/ │ └── script.js └── images/ └── logo.png- Navigate to AWS S3 Console
- Click "Create bucket"
- Enter a globally unique name (e.g.,
www.yourdomain.com) - Select region closest to your users
- Uncheck "Block all public access" and acknowledge
- Click "Create bucket"
- Select your bucket in S3 console
- Go to "Properties" tab
- Scroll to "Static website hosting"
- Click "Edit" and select "Enable"
- Specify index document (typically
index.html) - Click "Save changes"
- Go to "Permissions" tab
- Click "Bucket Policy"
- Add the following policy (replace bucket name):
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::www.yourdomain.com/*" } ] }You can upload manually via the AWS Console or use AWS CLI:
# Install AWS CLI if needed aws configure # Set up your credentials # Sync local files to S3 aws s3 sync ./your-site s3://www.yourdomain.com --delete- Navigate to CloudFront Console
- Click "Create distribution"
- Under Origin, select your S3 bucket
- Important: Select "Yes use OAI" and create new OAI
- Under "Default cache behavior", choose "Redirect HTTP to HTTPS"
- Under "Settings", specify your domain name (if you have one)
- Click "Create distribution" (Deployment takes ~15 minutes)
- Request a certificate in AWS Certificate Manager
- Add your domain (e.g.,
yourdomain.comandwww.yourdomain.com) - Verify ownership via DNS or email
- Update your CloudFront distribution to use this certificate
For Route 53:
- Create a new hosted zone for your domain
- Create an A record (Alias) pointing to your CloudFront distribution
- For www subdomain, create CNAME or another A record
For other providers:
- Create CNAME record pointing to your CloudFront domain (e.g.,
d123.cloudfront.net)
Set up automatic deployments when you push to GitHub:
-
Create a new IAM user with S3 and CloudFront permissions
-
Add secrets to your GitHub repo:
AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_S3_BUCKETAWS_CLOUDFRONT_DISTRIBUTION_ID
-
Add this GitHub Action workflow (
.github/workflows/deploy.yml):
name: Deploy to AWS on: push: branches: [ main ] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - 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: us-east-1 - name: Deploy to S3 run: | aws s3 sync ./ s3://${{ secrets.AWS_S3_BUCKET }} --delete - name: Invalidate CloudFront Cache run: | aws cloudfront create-invalidation \ --distribution-id ${{ secrets.AWS_CLOUDFRONT_DISTRIBUTION_ID }} \ --paths "/*"- S3 Storage: $0.023 per GB/month (first 50TB)
- CloudFront:
- $0.085 per GB data transfer out (first 10TB)
- $0.010 per 10,000 HTTPS requests
- Free Tier:
- 1 TB of CloudFront data transfer out
- 2 million CloudFront requests
- 5 GB of S3 storage
Estimated costs for small sites: <$1/month
Issue: 403 Forbidden when accessing site
- ✅ Verify bucket policy allows public read access
- ✅ Check if objects are publicly accessible in S3
Issue: Changes not appearing
- ✅ CloudFront cache takes time to invalidate (default 24h)
- ✅ Manually invalidate cache in CloudFront console
Issue: Mixed content warnings
- ✅ Ensure all resources use HTTPS URLs
- ✅ Set up proper redirects from HTTP to HTTPS
- In S3 static hosting settings, specify error document (e.g.,
404.html) - In CloudFront, create custom error responses
Configure CloudFront to return index.html for all paths:
- Go to your distribution
- Under "Error pages", create custom error response
- HTTP error code: 403 (or 404)
- Customize error response: Yes
- Response page path:
/index.html - HTTP response code: 200
MIT
## Key Features of This README: 1. Comprehensive Step-by-Step Guide: - From S3 bucket creation to CloudFront configuration - Includes both console and CLI methods 2. Visual Architecture Diagram: - Shows the relationship between components 3. CI/CD Automation: - Ready-to-use GitHub Actions workflow 4. Cost Optimization: - Clear pricing breakdown and free tier information 5. Troubleshooting Section: - Solutions for common issues 6. Advanced Configurations: - SPA routing, custom error pages, etc. 7. Multiple Deployment Methods: - Manual uploads and automated CI/CD Need a quick setup walkthrough? Follow my step-by-step guide here medium-walkthrough Don't forget to clap if you see it helpful
