Deploy to AWS
What Is AWS?
Section titled “What Is AWS?”Amazon Web Services (AWS) is the world’s largest cloud platform. It offers hundreds of services, but for a static site like Astro Docus, you only need two:
- Amazon S3 — Stores your built files (HTML, CSS, JS, images)
- Amazon CloudFront — A global CDN that caches and delivers those files to users worldwide
This is the recommended architecture for static sites on AWS. It is serverless, highly available, and costs virtually nothing for low-to-medium traffic .
AWS is more complex to set up than Cloudflare Pages or Netlify. But it gives you full control, and the free tier includes 5 GB of S3 storage and 1 TB of CloudFront data transfer per month .
Prerequisites
Section titled “Prerequisites”Before starting, you need:
- An AWS account (free tier available)
- Your Astro Docus project built locally (
npm run buildworks) - The
dist/folder generated - Basic familiarity with the AWS Console (we will guide you)
Architecture Overview
Section titled “Architecture Overview”User → CloudFront (CDN) → S3 Bucket (private)- S3 holds your files. It stays private — no public access.
- CloudFront reads from S3 using Origin Access Control (OAC) and serves content globally .
- HTTPS is provided by CloudFront automatically.
- Custom domain (optional) is configured via AWS Certificate Manager and Route 53.
This is more secure than the old “public S3 bucket” approach. Users never access S3 directly .
Step 1 — Create an S3 Bucket
Section titled “Step 1 — Create an S3 Bucket”- Log in to the AWS Management Console: https://console.aws.amazon.com/s3/
- Click Create bucket
- Enter a globally unique bucket name (e.g.,
astrodocus-site) - Choose a region close to you (e.g.,
us-east-1) - Leave “Block all public access” checked — we will use CloudFront, not public access
- Click Create bucket
Upload Your Build Files
Section titled “Upload Your Build Files”- Open your new bucket
- Click Upload
- Drag the contents of your
dist/folder (not the folder itself) into the upload area - Click Upload
Important: Upload the files inside
dist/, not thedistfolder itself. Theindex.htmlmust be at the root of the bucket.
Step 2 — Create a CloudFront Distribution
Section titled “Step 2 — Create a CloudFront Distribution”- Go to the CloudFront Console: https://console.aws.amazon.com/cloudfront/
- Click Create distribution
- For Origin domain, select your S3 bucket
- For Origin access, choose Origin access control settings (recommended)
- Click Create control setting — use the default name
- For Viewer protocol policy, choose Redirect HTTP to HTTPS
- For Default root object, enter
index.html - Leave other settings as default
- Click Create distribution
Update the S3 Bucket Policy
Section titled “Update the S3 Bucket Policy”After creating the distribution, CloudFront shows a bucket policy you need to copy. Go back to S3:
- Open your bucket → Permissions tab
- Click Bucket policy → Edit
- Paste the policy CloudFront provided
- Save
This grants CloudFront permission to read your bucket securely .
Get Your CloudFront URL
Section titled “Get Your CloudFront URL”In the CloudFront console, find your distribution’s Domain name (e.g., d111111abcdef8.cloudfront.net). Open this URL in your browser — your site should be live.
Step 3 — Automate with GitHub Actions (Optional)
Section titled “Step 3 — Automate with GitHub Actions (Optional)”Once the infrastructure is set up, you can automate deployments. Every push to main builds and deploys automatically .
Create an IAM User
Section titled “Create an IAM User”- Go to IAM Console → Users → Create user
- Name it
github-deploy - Attach a policy with these permissions:
s3:PutObject,s3:DeleteObject,s3:ListBucketcloudfront:CreateInvalidation
- Create the user and save the Access Key ID and Secret Access Key
Add Secrets to GitHub
Section titled “Add Secrets to GitHub”- Go to your GitHub repository → Settings → Secrets and variables → Actions
- Add these secrets :
| Secret Name | Value |
|---|---|
AWS_ACCESS_KEY_ID | Your IAM access key |
AWS_SECRET_ACCESS_KEY | Your IAM secret key |
AWS_REGION | us-east-1 |
S3_BUCKET | Your bucket name |
CLOUDFRONT_DISTRIBUTION_ID | Your distribution ID |
Add the Workflow File
Section titled “Add the Workflow File”Create .github/workflows/deploy.yml in your project :
name: Deploy to AWS S3 and CloudFront
on: push: branches: - main
jobs: build-and-deploy: runs-on: ubuntu-latest steps: - name: Checkout repository uses: actions/checkout@v4
- name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' cache: 'npm'
- name: Install dependencies run: npm ci
- name: Build Astro site run: npm run build
- name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v4 with: aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} aws-region: ${{ secrets.AWS_REGION }}
- name: Sync files to S3 run: | aws s3 sync dist/ s3://${{ secrets.S3_BUCKET }} --delete
- name: Invalidate CloudFront cache run: | aws cloudfront create-invalidation \ --distribution-id ${{ secrets.CLOUDFRONT_DISTRIBUTION_ID }} \ --paths "/*"Push this file to GitHub. The workflow runs on every push to main .
Step 4 — Add a Custom Domain (Optional)
Section titled “Step 4 — Add a Custom Domain (Optional)”A *.cloudfront.net URL works, but a custom domain looks more professional.
Request an SSL Certificate
Section titled “Request an SSL Certificate”- Go to AWS Certificate Manager (ACM) — must be in
us-east-1region - Click Request a certificate → Request a public certificate
- Enter your domain (e.g.,
docs.yourdomain.com) - Choose DNS validation
- Add the CNAME records to your DNS provider
- Wait for validation
Configure CloudFront
Section titled “Configure CloudFront”- Open your CloudFront distribution
- Click Edit
- Under Alternate domain name (CNAME), add your domain
- Under Custom SSL certificate, select your ACM certificate
- Save
Point DNS to CloudFront
Section titled “Point DNS to CloudFront”At your domain registrar, create a CNAME record:
docs.yourdomain.com → d111111abcdef8.cloudfront.netOr use Route 53 with an A record (alias) pointing to your CloudFront distribution .
Cost Overview
Section titled “Cost Overview”| Service | Free Tier | After Free Tier |
|---|---|---|
| S3 | 5 GB storage, 20,000 GET requests | ~$0.023/GB |
| CloudFront | 1 TB data transfer out/month | ~$0.085/GB |
| ACM | Free | Free |
| Route 53 | — | ~$0.50/month per hosted zone |
For a documentation site with moderate traffic, you will likely stay within the free tier .
Troubleshooting
Section titled “Troubleshooting”| Problem | Likely Cause | Fix |
|---|---|---|
| 403 Forbidden | Bucket policy missing | Paste the CloudFront policy into S3 |
| 404 on subpages | Missing index document | Set Default root object to index.html |
| Changes not showing | CloudFront cache | Create an invalidation (/*) |
| Custom domain not working | DNS not propagated | Wait, or verify CNAME |
| SSL error | Certificate not in us-east-1 | Re-request in the correct region |
Quick Recap
Section titled “Quick Recap”1. Create S3 bucket (private, no public access)2. Upload dist/ contents3. Create CloudFront distribution with OAC4. Copy bucket policy from CloudFront → paste into S35. Site is live at *.cloudfront.net6. (Optional) Automate with GitHub Actions7. (Optional) Add custom domain with ACM + Route 53AWS gives you full control and enterprise-grade reliability. The S3 + CloudFront pattern is the standard architecture for static sites on AWS .
👉 Next: docs/deploy-hosting/vps.md — deploy to a VPS.