Efficient Multi-Site Hosting with AWS: One S3 Bucket, Multiple Websites
Streamline Your Web Infrastructure with Amazon S3 and CloudFront Functions
As web developers and cloud architects, we often face the challenge of efficiently hosting multiple websites while maintaining security. In this blog post, we'll explore an elegant solution using Amazon S3 and CloudFront to host multiple websites from a single private S3 bucket. We'll walk through the process of setting up two subdomains, each serving content from different folders within the same bucket.
The Challenge
Imagine you need to host two separate websites: Site1 and Site2. You want to serve them under different subdomains (site1.example.com and site2.example.com) while keeping your S3 bucket private for enhanced security.
The Solution: Amazon S3 + CloudFront Functions
We'll leverage the power of Amazon S3 for storage and Amazon CloudFront for content delivery. Here's an overview of our architecture:
A private Amazon S3 bucket containing two folders: "site1" and "site2".
An Amazon CloudFront distribution to serve content and handle subdomain routing.
A custom CloudFront function to modify request URIs based on the subdomain.
Let's dive into the implementation details.
Step 1: Set Up Your S3 Bucket
Create a private S3 bucket with two folders:
site1/
site2/
Upload your website files to their respective folders.
Step 2: Create a CloudFront Distribution
Create a new CloudFront distribution
Set the origin to your private S3 bucket
Configure the default cache behavior:
Set "Viewer Protocol Policy" to "Redirect HTTP to HTTPS"
Set "Allowed HTTP Methods" to "GET, HEAD" (add others if needed)
Step 3: Implement a CloudFront Function
Create a new CloudFront function with the following code:
function handler(event) {
var request = event.request;
var headers = request.headers;
var host = headers.host.value;
var uri = request.uri;
if (host.startsWith("site2.")) {
if (uri === "/") {
request.uri = "/site2/index.html";
} else {
request.uri = "/site2" + uri;
}
} else if (host.startsWith("site1.")) {
if (uri === "/") {
request.uri = "/site1/index.html";
} else {
request.uri = "/site1" + uri;
}
}
return request;
}
Step 4: Associate the Function with Your Distribution
In your CloudFront distribution's settings:
Go to the "Behaviors" tab
Edit the default cache behavior
In the "Function Associations" section, add a new association:
Set "Event Type" to "Viewer Request"
Select the CloudFront function you created in Step 3
Step 5: Configure DNS
Update your DNS records to point the subdomains to your CloudFront distribution's domain name:
site1.example.com
→ [Your CloudFront Distribution Domain]site2.example.com
→ [Your CloudFront Distribution Domain]
The Result
With this setup, your websites will be served as follows:
https://site1.example.com/
serves content from the "site1" folder.https://site2.example.com/
serves content from the "site2" folder.
Your S3 bucket remains private, with access controlled through the CloudFront distribution. The CloudFront function handles subdomain routing, ensuring that the appropriate content is served based on the requested subdomain.
Additional Considerations
S3 Bucket Policy: Update your S3 bucket policy to grant necessary permissions to the CloudFront Origin Access Identity (OAI).
HTTPS: Ensure you have valid SSL certificates for your subdomains, which can be easily managed through AWS Certificate Manager.
Caching: Fine-tune CloudFront caching settings to optimize performance and reduce S3 requests.
Conclusion
This solution provides an efficient and secure way to host multiple websites from a single private S3 bucket using Amazon CloudFront. It offers several benefits:
Secure: Keep your S3 bucket private while serving content publicly
Scalable: Easily add more subdomains by updating the CloudFront function
Performant: Leverage CloudFront's global CDN for fast content delivery
By following this guide, you can streamline your web hosting infrastructure, enhance security, and improve the overall management of your multiple website projects.
Happy coding!