Static Site Hosting with Azure Storage and AWS S3
Introduction to Static Site Hosting on Cloud Storage
Static site hosting has become increasingly popular for deploying websites that don’t require server-side processing. Both Azure Blob Storage and AWS S3 provide cost-effective, scalable solutions for hosting static websites directly from cloud storage. This approach eliminates the need for traditional web servers, reduces operational costs, and provides excellent performance through global content delivery networks (CDNs).
In this post, we’ll explore how to use Azure Blob Storage and AWS S3 to host static websites, compare their features, and discuss best practices for deployment.
What is Static Site Hosting?
Static site hosting serves HTML, CSS, JavaScript, and other static assets directly to users without server-side processing. This is ideal for:
- Single Page Applications (SPAs) built with React, Vue, or Angular
- Documentation sites
- Personal blogs and portfolios
- Marketing and landing pages
- JAMstack applications
Benefits of Cloud Storage for Static Sites
- Cost-Effective: Pay only for storage and bandwidth used
- Scalability: Automatically handles traffic spikes
- High Availability: Built-in redundancy and durability
- Global Distribution: Easy integration with CDNs
- Simple Deployment: No server management required
- HTTPS Support: Built-in SSL/TLS certificates
Hosting Static Sites on Azure Blob Storage
Azure Blob Storage provides a dedicated static website hosting feature that makes it easy to serve static content directly from a storage container.
Prerequisites
- Azure subscription
- Azure CLI installed or Azure Portal access
- A static website ready to deploy
Step 1: Create a Storage Account
Using Azure CLI:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Set variables
RESOURCE_GROUP="my-static-site-rg"
LOCATION="eastus"
STORAGE_ACCOUNT_NAME="mystaticsite$(date +%s)"
# Create resource group
az group create \
--name $RESOURCE_GROUP \
--location $LOCATION
# Create storage account
az storage account create \
--name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP \
--location $LOCATION \
--sku Standard_LRS \
--kind StorageV2
Step 2: Enable Static Website Hosting
Enable the static website feature on your storage account:
1
2
3
4
5
6
# Enable static website hosting
az storage blob service-properties update \
--account-name $STORAGE_ACCOUNT_NAME \
--static-website \
--404-document 404.html \
--index-document index.html
This creates a special container named $web that serves as the root of your static website.
Step 3: Get the Website URL
Retrieve the primary endpoint for your static website:
1
2
3
4
5
6
# Get the static website URL
az storage account show \
--name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP \
--query "primaryEndpoints.web" \
--output tsv
The URL will look like: https://mystaticsite.z13.web.core.windows.net/
Step 4: Upload Your Static Content
Upload your website files to the $web container:
1
2
3
4
5
6
# Upload files
az storage blob upload-batch \
--account-name $STORAGE_ACCOUNT_NAME \
--source ./dist \
--destination '$web' \
--overwrite
For individual file uploads:
1
2
3
4
5
6
7
# Upload index.html
az storage blob upload \
--account-name $STORAGE_ACCOUNT_NAME \
--container-name '$web' \
--name index.html \
--file ./index.html \
--content-type "text/html"
Step 5: Configure Custom Domain (Optional)
To use a custom domain:
- Add a CNAME record in your DNS provider pointing to the storage account endpoint
- Map the custom domain in Azure:
1
2
3
4
az storage account update \
--name $STORAGE_ACCOUNT_NAME \
--resource-group $RESOURCE_GROUP \
--custom-domain www.yourdomain.com
Step 6: Enable CDN for Better Performance
For improved performance and HTTPS support with custom domains:
1
2
3
4
5
6
7
8
9
10
11
12
13
# Create CDN profile
az cdn profile create \
--name my-cdn-profile \
--resource-group $RESOURCE_GROUP \
--sku Standard_Microsoft
# Create CDN endpoint
az cdn endpoint create \
--name my-static-site \
--profile-name my-cdn-profile \
--resource-group $RESOURCE_GROUP \
--origin $STORAGE_ACCOUNT_NAME.z13.web.core.windows.net \
--origin-host-header $STORAGE_ACCOUNT_NAME.z13.web.core.windows.net
Hosting Static Sites on AWS S3
AWS S3 (Simple Storage Service) has been offering static website hosting for years and provides a robust, scalable solution.
Prerequisites
- AWS account
- AWS CLI configured with credentials
- A static website ready to deploy
Step 1: Create an S3 Bucket
Create a bucket with a name matching your domain (if using custom domain):
1
2
3
4
5
6
# Set variables
BUCKET_NAME="my-static-website.com"
REGION="us-east-1"
# Create bucket
aws s3 mb s3://$BUCKET_NAME --region $REGION
Step 2: Enable Static Website Hosting
Configure the bucket for static website hosting:
1
2
3
4
# Enable static website hosting
aws s3 website s3://$BUCKET_NAME/ \
--index-document index.html \
--error-document 404.html
Step 3: Configure Bucket Policy for Public Access
Create a bucket policy to allow public read access:
Create a file named bucket-policy.json:
1
2
3
4
5
6
7
8
9
10
11
12
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-static-website.com/*"
}
]
}
Apply the policy:
1
2
3
4
5
6
7
8
9
10
# Update bucket policy
aws s3api put-bucket-policy \
--bucket $BUCKET_NAME \
--policy file://bucket-policy.json
# Disable block public access
aws s3api put-public-access-block \
--bucket $BUCKET_NAME \
--public-access-block-configuration \
"BlockPublicAcls=false,IgnorePublicAcls=false,BlockPublicPolicy=false,RestrictPublicBuckets=false"
Step 4: Upload Your Static Content
Upload your website files:
1
2
3
4
5
6
7
# Upload entire directory
aws s3 sync ./dist s3://$BUCKET_NAME --delete
# Upload with cache control
aws s3 sync ./dist s3://$BUCKET_NAME \
--cache-control "max-age=3600" \
--delete
For individual files:
1
2
3
4
# Upload single file
aws s3 cp index.html s3://$BUCKET_NAME/ \
--content-type "text/html" \
--cache-control "max-age=3600"
Step 5: Get the Website URL
The website endpoint will be:
1
http://{bucket-name}.s3-website-{region}.amazonaws.com
For example:
1
http://my-static-website.com.s3-website-us-east-1.amazonaws.com
Step 6: Configure CloudFront for HTTPS and Custom Domain
For HTTPS support and better performance, set up CloudFront:
1
2
3
4
# Create CloudFront distribution
aws cloudfront create-distribution \
--origin-domain-name $BUCKET_NAME.s3-website-$REGION.amazonaws.com \
--default-root-object index.html
Or using a configuration file cloudfront-config.json:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
"CallerReference": "my-static-site-1",
"Comment": "Static website distribution",
"Enabled": true,
"DefaultRootObject": "index.html",
"Origins": {
"Quantity": 1,
"Items": [
{
"Id": "S3-my-static-website",
"DomainName": "my-static-website.com.s3-website-us-east-1.amazonaws.com",
"CustomOriginConfig": {
"HTTPPort": 80,
"HTTPSPort": 443,
"OriginProtocolPolicy": "http-only"
}
}
]
},
"DefaultCacheBehavior": {
"TargetOriginId": "S3-my-static-website",
"ViewerProtocolPolicy": "redirect-to-https",
"AllowedMethods": {
"Quantity": 2,
"Items": ["GET", "HEAD"]
},
"ForwardedValues": {
"QueryString": false,
"Cookies": {
"Forward": "none"
}
},
"MinTTL": 0
}
}
Comparison: Azure Blob Storage vs AWS S3
| Feature | Azure Blob Storage | AWS S3 |
|---|---|---|
| Pricing | ~$0.0184/GB/month | ~$0.023/GB/month |
| CDN Integration | Azure CDN | CloudFront |
| Custom Domain HTTPS | Requires Azure CDN | Requires CloudFront |
| Default Index | Supports index.html | Supports index.html |
| Error Pages | Single 404 page | Single error page |
| Directory Index | Not supported | Not supported |
| Setup Complexity | Low | Low |
| CLI Tools | Azure CLI | AWS CLI |
| SPA Routing | Requires CDN rules | Requires CloudFront functions |
Best Practices for Static Site Hosting
1. Use a CDN
Always use a CDN (Azure CDN or CloudFront) for production sites:
- Improved global performance
- HTTPS support for custom domains
- DDoS protection
- Better caching control
2. Set Proper Cache Headers
Configure appropriate cache headers for different file types:
1
2
3
4
5
6
7
8
9
10
# Azure: Upload with cache control
az storage blob upload \
--container-name '$web' \
--file style.css \
--name style.css \
--content-cache-control "public, max-age=31536000, immutable"
# AWS: Upload with cache control
aws s3 cp style.css s3://$BUCKET_NAME/ \
--cache-control "public, max-age=31536000, immutable"
3. Implement CI/CD
Automate deployments using GitHub Actions, Azure DevOps, or AWS CodePipeline:
Example GitHub Action for Azure:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
name: Deploy to Azure Storage
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: npm run build
- name: Deploy to Azure
uses: azure/CLI@v1
with:
inlineScript: |
az storage blob upload-batch \
--account-name $ \
--source ./dist \
--destination '$web' \
--overwrite
Example GitHub Action for AWS:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
name: Deploy to S3
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Build
run: npm run build
- name: Deploy to S3
env:
AWS_ACCESS_KEY_ID: $
AWS_SECRET_ACCESS_KEY: $
run: |
aws s3 sync ./dist s3://$ --delete
4. Handle SPA Routing
For Single Page Applications with client-side routing, configure your CDN to redirect all routes to index.html:
Azure CDN: Create URL rewrite rules CloudFront: Use CloudFront Functions or Lambda@Edge
5. Enable Compression
Enable gzip/brotli compression:
1
2
3
4
5
6
7
8
9
# Azure: Upload pre-compressed files
az storage blob upload \
--file styles.css.gz \
--name styles.css \
--content-encoding gzip
# AWS: Upload pre-compressed files
aws s3 cp styles.css.gz s3://$BUCKET_NAME/styles.css \
--content-encoding gzip
6. Security Considerations
- Use HTTPS for all production sites
- Implement Content Security Policy (CSP) headers
- Set appropriate CORS policies
- Regularly update dependencies
- Monitor access logs
- Use IAM roles with minimal permissions
7. Cost Optimization
- Set lifecycle policies to delete old versions
- Use appropriate storage tiers
- Monitor bandwidth usage
- Implement proper caching to reduce origin requests
- Clean up unused resources
Conclusion
Both Azure Blob Storage and AWS S3 provide excellent platforms for hosting static websites. The choice between them often depends on:
- Your existing cloud infrastructure
- Specific feature requirements
- Regional availability
- Cost considerations
- Team expertise
For most use cases, both platforms offer comparable performance and features. Azure Blob Storage might be preferable if you’re already using Azure services, while AWS S3 is a great choice if you’re in the AWS ecosystem.
Key takeaways:
- Static site hosting on cloud storage is cost-effective and scalable
- Always use a CDN for production deployments
- Implement proper caching strategies
- Automate deployments with CI/CD
- Follow security best practices
By leveraging cloud storage for static site hosting, you can build and deploy modern web applications with minimal operational overhead while maintaining excellent performance and reliability.