AWS
How to Host a Static Website on AWS S3 (Step-by-Step Guide)
Learn how to host your static website on Amazon S3, configure permissions, and set up custom domains with CloudFront.
March 20, 2024
Tech Writer
6 min read
How to Host a Static Website on AWS S3
S3 Static Website Architecture
graph LR
    Users((Users)) --> CF[CloudFront]
    CF --> S3[S3 Bucket]
    S3 --> Index[index.html]
    S3 --> Error[error.html]
    S3 --> Assets[Static Assets]
    
    subgraph Security
        WAF[AWS WAF] --> CF
        ACM[ACM Certificate] --> CF
    end
    
    subgraph DNS
        Route53[Route 53] --> CF
    end
What You'll Learn
- Setting up an S3 bucket for static website hosting
- Configuring bucket permissions and policies
- Enabling HTTPS with CloudFront
- Setting up custom domains with Route 53
- Implementing security best practices
- Optimizing performance and costs
- Troubleshooting common issues
Prerequisites
Required Tools and Services
| Requirement | Purpose | Notes | 
|---|---|---|
| AWS Account | Service access | Free tier eligible | 
| AWS CLI | Command-line management | Version 2.x recommended | 
| Domain Name | Custom URL (optional) | Can use Route 53 or external registrar | 
Website Files Preparation
| File Type | Required | Best Practice | 
|---|---|---|
| HTML files | Yes | Minified for production | 
| CSS/JavaScript | Optional | Bundled and minified | 
| Images | Optional | Optimized and compressed | 
Step 1: Create and Configure S3 Bucket
Using AWS CLI
# Create S3 bucket aws s3api create-bucket \ --bucket your-website-bucket \ --region us-east-1 # Enable website hosting aws s3api put-bucket-website \ --bucket your-website-bucket \ --website-configuration file://website-config.json
Website Configuration (website-config.json)
{ "IndexDocument": { "Suffix": "index.html" }, "ErrorDocument": { "Key": "error.html" } }
Bucket Policy Configuration
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": [ "s3:GetObject" ], "Resource": "arn:aws:s3:::your-website-bucket/*" } ] }
CORS Configuration (if needed)
{ "CORSRules": [ { "AllowedOrigins": ["*"], "AllowedMethods": ["GET"], "MaxAgeSeconds": 3000, "AllowedHeaders": ["Authorization", "Content-Length"] } ] }
Step 2: Upload Website Content
File Organization
your-website/ ├── index.html ├── error.html ├── assets/ │ ├── css/ │ │ └── styles.css │ ├── js/ │ │ └── main.js │ └── images/ │ └── logo.png ├── blog/ │ └── index.html └── about/ └── index.html
Upload Commands
# Upload all files with proper content types aws s3 sync . s3://your-website-bucket \ --exclude "*.DS_Store" \ --exclude "node_modules/*" \ --include "*.html" \ --include "*.css" \ --include "*.js" \ --include "*.jpg" \ --include "*.png" \ --cache-control "max-age=86400"
Content Type Mapping
| File Type | Content-Type | Cache Control | 
|---|---|---|
| .html | text/html | no-cache | 
| .css | text/css | max-age=604800 | 
| .js | application/javascript | max-age=604800 | 
| images | image/[type] | max-age=31536000 | 
Step 3: CloudFront Configuration
Distribution Settings
| Setting | Value | Explanation | 
|---|---|---|
| Origin Domain | bucket-name.s3-website-region.amazonaws.com | S3 website endpoint | 
| Origin Path | / | Root path | 
| Viewer Protocol Policy | Redirect HTTP to HTTPS | Force HTTPS | 
| Allowed HTTP Methods | GET, HEAD | Static content only | 
| Cache Policy | CachingOptimized | Best for static sites | 
| Price Class | Use All Edge Locations | Global distribution | 
Function Associations
| Function Type | Purpose | Example | 
|---|---|---|
| Viewer Request | URL rewriting | Add index.html | 
| Origin Request | Header modification | Add security headers | 
| Origin Response | Response modification | Add CORS headers | 
Step 4: Custom Domain Configuration
ACM Certificate Request
# Request certificate aws acm request-certificate \ --domain-name example.com \ --validation-method DNS \ --subject-alternative-names www.example.com
Route 53 Configuration
| Record Type | Name | Value | TTL | 
|---|---|---|---|
| A (Alias) | example.com | CloudFront distribution | Automatic | 
| CNAME | www | CloudFront domain | 300 seconds | 
| AAAA (Alias) | example.com | CloudFront distribution | Automatic | 
Advanced Configuration
Security Headers
{ "Strict-Transport-Security": "max-age=31536000; includeSubdomains; preload", "Content-Security-Policy": "default-src 'self'", "X-Content-Type-Options": "nosniff", "X-Frame-Options": "DENY", "X-XSS-Protection": "1; mode=block", "Referrer-Policy": "strict-origin-when-cross-origin" }
Error Page Configuration
{ "ErrorDocument": { "Key": "error.html" }, "RoutingRules": [ { "Condition": { "HttpErrorCodeReturnedEquals": "404" }, "Redirect": { "HostName": "example.com", "ReplaceKeyWith": "404.html" } } ] }
Performance Optimization
CloudFront Cache Behaviors
| Path Pattern | TTL Settings | Compression | 
|---|---|---|
| /*.html | 0 seconds | Yes | 
| /assets/images/* | 1 year | No | 
| /assets/css/* | 1 week | Yes | 
| /assets/js/* | 1 week | Yes | 
Image Optimization
| Format | Use Case | Optimization Tool | 
|---|---|---|
| WebP | Modern browsers | cwebp | 
| JPEG | Photos | jpegoptim | 
| PNG | Icons/logos | pngquant | 
Monitoring and Analytics
CloudWatch Metrics
| Metric | Description | Threshold | 
|---|---|---|
| Requests | Total requests | Monitor trends | 
| BytesDownloaded | Data transfer | Cost control | 
| 4xxErrorRate | Client errors | Less than 1% | 
| 5xxErrorRate | Server errors | Less than 0.1% | 
Cost Management
Cost Optimization Strategies
- 
Storage Optimization - Enable lifecycle policies
- Remove unused files
- Use appropriate storage class
 
- 
CloudFront Optimization - Choose appropriate price class
- Optimize cache hit ratio
- Monitor data transfer
 
- 
Request Optimization - Bundle and minify assets
- Use appropriate cache settings
- Implement lazy loading
 
Monthly Cost Estimation
| Component | Usage | Estimated Cost | 
|---|---|---|
| S3 Storage | 1 GB | $0.023 | 
| Data Transfer | 100 GB | $8.50 | 
| Requests | 1M | $0.40 | 
Maintenance and Updates
Regular Tasks
- 
Weekly - Monitor error rates
- Check access logs
- Review security findings
 
- 
Monthly - Update content
- Review metrics
- Cost analysis
 
- 
Quarterly - Security assessment
- Performance optimization
- Infrastructure review
 
Troubleshooting Guide
Common Issues and Solutions
| Issue | Possible Cause | Solution | 
|---|---|---|
| 403 Forbidden | Bucket policy | Verify permissions | 
| HTTPS not working | SSL certificate | Check ACM setup | 
| Slow loading | Cache settings | Optimize CloudFront | 
| 404 errors | Missing files | Check file paths | 
Conclusion
Hosting a static website on AWS S3 with CloudFront provides a scalable, secure, and cost-effective solution. By following this comprehensive guide and implementing the best practices, you can create a high-performance website with global reach.
Additional Resources
AWS
S3
Static Website
CloudFront
Hosting