AWS
AWS Overview
Amazon Web Services (AWS) is a cloud platform offering compute, storage, networking, and managed services. This page covers the core services used to run this site, plus key steps to replicate the setup.
Services
| Service | Category | Analogy | Best For... |
|---|---|---|---|
| EC2 | Compute | A rented PC | Full control over the environment. |
| Lambda | Compute | A light switch | Running code only when triggered. |
| S3 | Storage | A bottomless warehouse | "Files, images, and backups." |
| RDS | Database | A managed library | Structured data (SQL). |
| DynamoDB | Database | A high-speed post-it wall | "Fast, simple key-value data (NoSQL)." |
| Amazon VPC (Virtual Private Cloud) | Networking | Your own private section of the internet | Creating a private network for your resources. |
| Route 53 | Networking | A phone book for the internet | Managing domain names and routing traffic. |
| CloudFront | Networking | A global CDN | Speeding up delivery of your website content. |
| Elastic Load Balancing (ELB) | Networking | A traffic cop | Distributing incoming traffic across multiple instances. |
| Elastic Container Service (ECS) | Compute | A container manager | Running and managing Docker containers at scale. |
| Elastic Kubernetes Service (EKS) | Compute | A Kubernetes manager | Running and managing Kubernetes clusters. |
IAM
IAM (Identity and Access Management) controls who can do what inside your AWS account.
Root Account ← master key, use only for initial setup
↓ creates
IAM Admin User ← your daily driver
↓ creates
Roles / Policies for services (Amplify, Lambda, S3, etc.)
Account structure:
IAM Account
├── Users → people (you, teammates)
├── Groups → collections of users ("developers", "admins")
├── Roles → worn by AWS services (Amplify, Lambda, EC2)
└── Policies → permission rules attached to any of the above
Key rules:
- Never use the root account for day-to-day work
- Grant least privilege — only the permissions actually needed
- Use roles for service-to-service access, not user credentials
- Keep all resources in the same region
Setup steps:
- Sign in as root → IAM → Create admin user with
AdministratorAccess - Enable MFA on both root and admin user
- Create a dedicated IAM user for programmatic access (S3 writes, CLI)
- Attach only the policies that user needs — no
AdministratorAccess - Store the access key ID and secret in a password manager, never in code
S3
S3 (Simple Storage Service) stores files as objects inside buckets. It's used here to host all images for this site.
Bucket structure for this site:
mynote-storage/
└── public/
└── images/
├── cs/
└── web/
Setup steps:
- S3 → Create bucket → choose region → uncheck "Block all public access"
- Bucket → Permissions → Bucket policy → paste the public read policy below
- Create an IAM user with write-only policy → generate access keys
- Store keys as environment variables (never hardcode)
Public read policy — allows anyone to fetch objects:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-bucket-name/*"
}]
}
IAM policy for programmatic write access (used by Nuxt Studio to upload images):
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:DeleteObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:::your-bucket-name",
"arn:aws:s3:::your-bucket-name/*"
]
}]
}
Images are referenced in markdown as /images/web/example.svg. A custom ProseImg component resolves these to the full S3 URL at render time:
/images/web/aws.svg
→ https://your-bucket.s3.region.amazonaws.com/public/images/web/aws.svg
AWS Amplify
Amplify Hosting is a managed CI/CD and hosting platform. Push to GitHub → Amplify builds and deploys automatically.
How it works:
GitHub / GitLab push
↓
Amplify detects change
↓
CodeBuild: npm ci → nuxt build
↓
Static files → Amplify CDN (CloudFront)
SSR routes → Lambda function (Node.js)
↓
Custom domain via Route 53 / DNS
Setting up Amplify for a Nuxt SSR app
1. Connect your repository
Go to AWS Amplify Console → New app → Host web app → Connect GitHub or GitLab.
2. Build settings
Amplify auto-detects Nuxt. Verify or set the build spec:
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- npm run build
artifacts:
baseDirectory: .amplify-hosting
files:
- '**/*'
cache:
paths:
- node_modules/**/*
3. Environment variables
Set these in Amplify Console → App settings → Environment variables:
| Variable | Purpose |
|---|---|
S3_ACCESS_KEY_ID | IAM user key for S3 writes |
S3_SECRET_ACCESS_KEY | IAM user secret |
S3_BUCKET | Bucket name |
S3_REGION | e.g. ap-northeast-1 |
S3_ENDPOINT | e.g. https://s3.ap-northeast-1.amazonaws.com |
AI_GATEWAY_API_KEY | Vercel AI Gateway key for the assistant |
4. Node.js version
Nuxt Content v3 requires Node 22 for node:sqlite. Set this in Amplify Console → Build settings → Live package updates → Node.js version = 22.
Alternatively, set it in nuxt.config.ts:
nitro: {
preset: 'aws-amplify',
awsAmplify: {
runtime: 'nodejs22.x',
},
}
5. Service role
Amplify needs an IAM service role to deploy Lambda and CloudFront resources. Create a role with the AdministratorAccess-Amplify managed policy, then attach it in App settings → General → Service role.
6. Custom domain
App settings → Domain management → Add domain. Amplify provisions an SSL certificate automatically via ACM. Point your DNS CNAME to the Amplify domain.
Monitoring builds
Build logs are in Amplify Console → your app → the build job. You can also fetch them via CLI:
# List recent builds
aws amplify list-jobs --app-id <app-id> --branch-name main
# Get a specific build's log URL
aws amplify get-job --app-id <app-id> --branch-name main --job-id <id>
Lambda runtime logs go to CloudWatch → Log groups → /aws/lambda/amplify-<app-id>-<branch>-<function>.
CloudFront
CloudFront is AWS's CDN. Amplify uses it automatically to serve static assets globally with low latency. You don't configure it directly — Amplify manages it — but it's useful to know it's there when debugging cache issues.
To force a cache invalidation after a deploy:
aws cloudfront create-invalidation --distribution-id <id> --paths "/*"
How This Site Is Set Up
This site is a Docus documentation site deployed on AWS Amplify.
Stack:
Nuxt 4 + Docus theme
├── @nuxt/content v3 ← markdown files in content/
├── @nuxtjs/i18n ← English + French
└── motion-v ← animations
↓ builds with
Nitro (aws-amplify preset)
↓ deploys to
Amplify Hosting
├── Static HTML (prerendered pages) → CloudFront CDN
└── Lambda (Node 22) → SSR + content queries
Image serving:
Markdown images use /images/... paths. A custom ProseImg.vue component maps these to absolute S3 URLs at render time, bypassing Amplify's image optimizer (which runs at CDN level and can't reach Lambda proxy routes).
AI assistant:
Docus's built-in assistant is enabled. It uses an MCP server at /mcp to search the documentation, and routes AI calls through Vercel AI Gateway (AI_GATEWAY_API_KEY). Model: google/gemini-2.5-flash-preview.
Dev-only modules (not loaded in production Lambda):
@nuxthub/core— NuxtHub blob driver, lets Nuxt Studio upload images to S3nuxt-studio— connects to studio.nuxt.com for visual editing
Key config:
// nuxt.config.ts
const isProd = process.env.NODE_ENV === 'production'
export default defineNuxtConfig({
modules: [
...(isProd ? [] : ['@nuxthub/core', 'nuxt-studio']),
'@nuxt/content',
// ...
],
nitro: {
preset: 'aws-amplify',
awsAmplify: { runtime: 'nodejs22.x' },
},
})
Repositories:
- GitHub: NutNut17/mynote →
mynote.nut17.com - GitLab:
backup/mainbranch →mynote2.nut17.com(mirror)