TL;DR
Learn how to host your static website on Amazon S3, configure permissions, and set up custom domains with CloudFront.
How to Host a Static Website on AWS S3
`` 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
mermaid
`
$1
$1
$1
| 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 |
$1
| File Type | Required | Best Practice |
|---|---|---|
| HTML files | Yes | Minified for production |
| CSS/JavaScript | Optional | Bundled and minified |
| Images | Optional | Optimized and compressed |
$1
$1
` aws s3api create-bucket \
--bucket your-website-bucket \
--region us-east-1 aws s3api put-bucket-website \
--bucket your-website-bucket \
--website-configuration file://website-config.json
bash
`Create S3 bucket
Enable website hosting
$1
` {
"IndexDocument": {
"Suffix": "index.html"
},
"ErrorDocument": {
"Key": "error.html"
}
}
json
`
$1
` {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": [
"s3:GetObject"
],
"Resource": "arn:aws:s3:::your-website-bucket/*"
}
]
}
json
`
$1
` {
"CORSRules": [
{
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET"],
"MaxAgeSeconds": 3000,
"AllowedHeaders": ["Authorization", "Content-Length"]
}
]
}
json
`
$1
$1
` your-website/
├── index.html
├── error.html
├── assets/
│ ├── css/
│ │ └── styles.css
│ ├── js/
│ │ └── main.js
│ └── images/
│ └── logo.png
├── blog/
│ └── index.html
└── about/
└── index.html
plaintext
`
$1
` 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"
bash
`Upload all files with proper content types
$1
| 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 |
$1
$1
| 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 |
$1
| 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 |
$1
$1
` aws acm request-certificate \
--domain-name example.com \
--validation-method DNS \
--subject-alternative-names www.example.com
bash
`Request certificate
$1
| 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 |
$1
$1
` {
"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"
}
json
`
$1
` {
"ErrorDocument": {
"Key": "error.html"
},
"RoutingRules": [
{
"Condition": {
"HttpErrorCodeReturnedEquals": "404"
},
"Redirect": {
"HostName": "example.com",
"ReplaceKeyWith": "404.html"
}
}
]
}
json
``
$1
$1
| Path Pattern | TTL Settings | Compression |
|---|---|---|
| /*.html | 0 seconds | Yes |
| /assets/images/* | 1 year | No |
| /assets/css/* | 1 week | Yes |
| /assets/js/* | 1 week | Yes |
$1
| Format | Use Case | Optimization Tool |
|---|---|---|
| WebP | Modern browsers | cwebp |
| JPEG | Photos | jpegoptim |
| PNG | Icons/logos | pngquant |
$1
$1
| 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% |
$1
$1
1. Storage Optimization
- Enable lifecycle policies
- Remove unused files
- Use appropriate storage class
2. CloudFront Optimization
- Choose appropriate price class
- Optimize cache hit ratio
- Monitor data transfer
3. Request Optimization
- Bundle and minify assets
- Use appropriate cache settings
- Implement lazy loading
$1
| Component | Usage | Estimated Cost |
|---|---|---|
| S3 Storage | 1 GB | $0.023 |
| Data Transfer | 100 GB | $8.50 |
| Requests | 1M | $0.40 |
$1
$1
1. Weekly
- Monitor error rates
- Check access logs
- Review security findings
2. Monthly
- Update content
- Review metrics
- Cost analysis
3. Quarterly
- Security assessment
- Performance optimization
- Infrastructure review
$1
$1
| 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 |
$1
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.
$1
1. [AWS S3 Documentation](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html)
2. [CloudFront Developer Guide](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Introduction.html)
3. [AWS Pricing Calculator](https://calculator.aws)
4. [AWS Well-Architected Framework](https://aws.amazon.com/architecture/well-architected/)
5. [Static Website Security Guide](https://aws.amazon.com/blogs/networking-and-content-delivery/)
Why This Matters
Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.
Trade-offs to Consider
Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.
When NOT to Use This
Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.
Decision Framework
Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.