# 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