S3 markdown file
This commit is contained in:
127
backend/S3.md
Normal file
127
backend/S3.md
Normal file
@@ -0,0 +1,127 @@
|
||||
# AWS S3 Image Storage Integration Plan
|
||||
|
||||
## Overview
|
||||
|
||||
Integrate AWS S3 for image storage using **direct-to-S3 uploads with presigned URLs**. Frontend will upload directly to S3, reducing backend load. Images will use a **hybrid access model**: public URLs for profiles/items/forum, private signed URLs for messages and condition-checks.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
Frontend Backend AWS S3
|
||||
│ │ │
|
||||
│ 1. POST /api/upload/presign │ │
|
||||
│────────────────────────────────>│ │
|
||||
│ │ 2. Generate presigned URL │
|
||||
│ 3. Return {uploadUrl, key} │ │
|
||||
│<────────────────────────────────│ │
|
||||
│ │ │
|
||||
│ 4. PUT file directly to S3 │ │
|
||||
│────────────────────────────────────────────────────────────────>│
|
||||
│ │ │
|
||||
│ 5. POST /api/upload/confirm │ │
|
||||
│────────────────────────────────>│ 6. Verify object exists │
|
||||
│ │──────────────────────────────>│
|
||||
│ 7. Return confirmation │ │
|
||||
│<────────────────────────────────│ │
|
||||
```
|
||||
|
||||
## S3 Bucket Structure
|
||||
|
||||
```
|
||||
s3://village-share-{env}/
|
||||
├── profiles/{uuid}.{ext} # Public access
|
||||
├── items/{uuid}.{ext} # Public access
|
||||
├── forum/{uuid}.{ext} # Public access
|
||||
├── messages/{uuid}.{ext} # Private (signed URLs)
|
||||
└── condition-checks/{uuid}.{ext} # Private (signed URLs)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### AWS S3 Bucket Setup
|
||||
|
||||
#### Bucket Policy (Hybrid: Public + Private)
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Sid": "PublicRead",
|
||||
"Effect": "Allow",
|
||||
"Principal": "*",
|
||||
"Action": "s3:GetObject",
|
||||
"Resource": [
|
||||
"arn:aws:s3:::village-share-dev/profiles/*",
|
||||
"arn:aws:s3:::village-share-dev/items/*",
|
||||
"arn:aws:s3:::village-share-dev/forum/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note: `messages/*` and `condition-checks/*` are NOT included - require signed URLs.
|
||||
|
||||
#### CORS Configuration
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"AllowedHeaders": [
|
||||
"Content-Type",
|
||||
"Content-Length",
|
||||
"Content-Disposition",
|
||||
"Cache-Control",
|
||||
"x-amz-content-sha256",
|
||||
"x-amz-date",
|
||||
"x-amz-security-token"
|
||||
],
|
||||
"AllowedMethods": ["PUT", "GET"],
|
||||
"AllowedOrigins": ["http://localhost:3000"],
|
||||
"ExposeHeaders": ["ETag"],
|
||||
"MaxAgeSeconds": 3600
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
#### IAM Policy for Backend
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": ["s3:PutObject", "s3:GetObject"],
|
||||
"Resource": "arn:aws:s3:::village-share-dev/*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
**Security Note:** `s3:DeleteObject` is intentionally NOT included. File deletion is not exposed via the API to prevent unauthorized deletion attacks. Use S3 lifecycle policies for cleanup instead.
|
||||
|
||||
## Environment Variables to Add
|
||||
|
||||
```bash
|
||||
# Backend (.env)
|
||||
S3_ENABLED=true # Set to "true" to enable S3
|
||||
S3_BUCKET=village-share-{env}
|
||||
|
||||
# Frontend (.env)
|
||||
REACT_APP_S3_BUCKET=village-share-{env}
|
||||
REACT_APP_AWS_REGION=us-east-1
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Deployment Checklist
|
||||
|
||||
1. Create S3 buckets for each environment (dev, qa, prod)
|
||||
2. Apply bucket policies (public folders + private messages)
|
||||
3. Configure CORS on each bucket
|
||||
4. Attach IAM policy to EC2/ECS role
|
||||
5. Add environment variables
|
||||
6. Deploy backend changes
|
||||
7. Deploy frontend changes
|
||||
Reference in New Issue
Block a user