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