File size: 2,389 Bytes
05c5ed5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# S3 Storage Setup

This app supports S3 for file uploads (dev/prod). Development can rely on presigned PUTs directly from the browser, while production should keep the bucket private and serve via CDN (CloudFront + Origin Access Control) or signed GET URLs.

## Buckets
- Pick a region (e.g., `us-east-2`)
  - Dev/Test example: `better-chatbot-dev` (public GET on `uploads/` only if needed)
  - Prod example: `better-chatbot-prod` (private)
- Enable default encryption (SSE-S3) and versioning on both buckets.

## CORS
- Dev bucket: allow PUT/GET/HEAD from the origins you use locally and in staging, for example:
  - `http://localhost:3000`, `http://127.0.0.1:3000`
  - `https://staging.your-domain.com`, `http://staging.your-domain.com`
- Prod bucket: allow GET/HEAD only from your production domain (e.g., `https://app.your-domain.com`). Avoid enabling browser PUT in production.

## Dev public-read policy (prefix-only)
Grant public GET for the `uploads/` prefix on the dev bucket only if you need unauthenticated downloads:
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowPublicReadForUploadsPrefix",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::better-chatbot-dev/uploads/*"
    }
  ]
}
```

## IAM (app runtime)
Least privilege for app role/user:
- Actions: `s3:PutObject`, `s3:GetObject`, `s3:DeleteObject`, `s3:HeadObject`
- Resources: `arn:aws:s3:::<bucket-name>/uploads/*`

## Env configuration
- Dev/local:
  - `FILE_STORAGE_TYPE=s3`
  - `FILE_STORAGE_PREFIX=uploads`
  - `FILE_STORAGE_S3_BUCKET=better-chatbot-dev`
  - `FILE_STORAGE_S3_REGION=us-east-2` (or set `AWS_REGION`)
  - Use AWS SSO/profile or `AWS_ACCESS_KEY_ID`/`AWS_SECRET_ACCESS_KEY`
- Prod:
  - `FILE_STORAGE_S3_BUCKET=better-chatbot-prod`
  - Prefer CloudFront; set `FILE_STORAGE_S3_PUBLIC_BASE_URL=https://<cdn-domain>`

## Verify locally
- Ensure `aws sso login --profile <your_profile>` (or credentials are already available).
- Test presign script:
```
AWS_PROFILE=<your_profile> \
FILE_STORAGE_TYPE=s3 \
FILE_STORAGE_S3_BUCKET=better-chatbot-dev \
FILE_STORAGE_S3_REGION=us-east-2 \
pnpm tsx scripts/verify-s3-upload-url.ts
```
- You should get `{ directUploadSupported: true, url, key, method: PUT }`.
- Upload with curl (optional): `curl -X PUT -H "Content-Type: image/png" --data-binary @file.png "<url>"`.