Architecture Overview
Create the S3 Bucket (Storage)
We will create a bucket that is not public. Only CloudFront will be allowed to read from it.
- Log in to the AWS Console and go to S3.
- Click Create bucket.
- Bucket name: your-domain-name.com (e.g., 52apps.example.com).
- Region: Choose a region close to you (e.g., us-east-1).
- Block Public Access: Ensure "Block all public access" is CHECKED.
- Bucket Versioning: Enable (Recommended for recovery).
- Encryption: Server-side encryption with Amazon S3 managed keys (SSE-S3).
- Click Create bucket.
Request SSL Certificate (Security)
- Go to AWS Certificate Manager (ACM).
- Switch Region to US East (N. Virginia) us-east-1.
- Click Request > Request a public certificate.
- Domain names: Add your-domain-name.com and *.your-domain-name.com.
- Validation method: DNS validation.
- Click Request.
- Click on the Certificate ID, then click Create records in Route 53 to automatically add validation CNAMEs.
- Wait for status to change to Issued.
Create CloudFront Distribution (CDN & Security)
This is the most critical step for security.
Origin Settings:
- Origin domain: Select your S3 bucket from Step 1.
- Origin access: Select Origin access control settings (recommended).
- Click Create control setting (keep defaults) and Create.
Viewer Settings:
- Viewer protocol policy: Select Redirect HTTP to HTTPS.
- Allowed HTTP methods: GET, HEAD, OPTIONS.
- Cache key and origin requests: Select CachingOptimized.
Response headers policy (Security Headers):
Click Create policy. Name it StaticSiteSecurityPolicy.
- Strict-Transport-Security (HSTS): Enable. max-age: 31536000, includeSubDomains: Yes, preload: Yes.
- X-Content-Type-Options: Enable (nosniff).
- X-Frame-Options: Enable (DENY or SAMEORIGIN).
- X-XSS-Protection: Enable (1; mode=block).
- Referrer-Policy: Enable (strict-origin-when-cross-origin).
- Content-Security-Policy (CSP): Enable. Use the value below:
default-src 'self'; script-src 'self' 'unsafe-inline' https://cdn.tailwindcss.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' https: data:; font-src 'self' https://fonts.gstatic.com; connect-src 'self'; object-src 'none'; frame-ancestors 'none'; upgrade-insecure-requests;
Click Create and select this new policy in the dropdown.
- Settings: Alternate domain name (CNAME): Enter your-domain-name.com.
- Custom SSL certificate: Select the ACM certificate created in Step 2.
- Default root object: index.html.
- Click Create distribution.
Important:
After creation, you will see a banner saying "The S3 bucket policy needs to be updated".
- Click Copy policy.
- Go to your S3 Bucket > Permissions > Bucket policy.
- Paste the policy and Save. This grants CloudFront permission to read your private bucket.
Configure Route 53 (DNS)
- Go to Route 53 > Hosted zones.
- Click on your domain name.
- Click Create record.
- Record name: Leave blank (for root domain) or enter subdomain (e.g., www).
- Record type: A.
- Alias: Toggle Alias to ON.
- Route traffic to: Alias to CloudFront distribution.
- Region: US East (N. Virginia).
- Choose your distribution from the list.
- Click Create records.
Deploy Your Code
You can use the AWS CLI to sync your local files to the S3 bucket.
- Install AWS CLI and configure it (aws configure) with your credentials.
- Run the following command from your project root folder:
# Replace with your actual bucket name aws s3 sync . s3://your-domain-name.com --delete --exclude ".git/*" --exclude ".vscode/*" --exclude ".DS_Store"
- Invalidate CloudFront Cache (so users see changes immediately):
# Replace with your Distribution ID (e.g., E1XXXXXX) aws cloudfront create-invalidation --distribution-id YOUR_DIST_ID --paths "/*"
Summary of Security Measures Implemented
- S3 Private Access The bucket is not public. Users cannot bypass CloudFront to access S3 directly.
- HTTPS Enforcement HTTP traffic is automatically redirected to HTTPS.
- HSTS Tells browsers to remember to use HTTPS only for your site.
- Content Security Policy (CSP) The most effective protection against XSS. It ensures scripts can only run from your domain and the specific CDNs you use (Tailwind, Google Fonts).
- X-Frame-Options Prevents your site from being embedded in iframes (Clickjacking protection).
Optional: Deployment Script
You can create a file named deploy.sh in your root folder to automate this:
#!/bin/bash BUCKET_NAME="your-domain-name.com" DISTRIBUTION_ID="YOUR_DISTRIBUTION_ID" echo "🚀 Deploying to S3..." aws s3 sync . s3://$BUCKET_NAME --delete --exclude ".git/*" --exclude ".vscode/*" --exclude ".DS_Store" echo "🔄 Invalidating CloudFront Cache..." aws cloudfront create-invalidation --distribution-id $DISTRIBUTION_ID --paths "/*" echo "✅ Deployment Complete!"
Make it executable: chmod +x deploy.sh and run ./deploy.sh.