diff --git a/backend/S3.md b/backend/S3.md new file mode 100644 index 0000000..ffbd70e --- /dev/null +++ b/backend/S3.md @@ -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