diff --git a/.artifacts/2026-02-06_20-00_minio-s3-storage-setup.md b/.artifacts/2026-02-06_20-00_minio-s3-storage-setup.md new file mode 100644 index 0000000..6b255e4 --- /dev/null +++ b/.artifacts/2026-02-06_20-00_minio-s3-storage-setup.md @@ -0,0 +1,158 @@ +# MinIO S3 Storage Setup for nuc-portal + +**Date:** 2026-02-06 20:00 +**Context:** Added S3-compatible storage for deployment preview screenshots + +--- + +## MinIO Configuration + +### Access Details + +| Property | Value | +|----------|-------| +| **API Endpoint** | `http://192.168.1.3:9000` | +| **Console** | `http://192.168.1.3:9001` | +| **Root User** | `minioadmin` | +| **Root Password** | `minioadmin` | + +### nuc-portal Service Account + +| Property | Value | +|----------|-------| +| **Access Key** | `nuc-portal` | +| **Secret Key** | `YpVhIltqY6itWQXHWbEzJ82O9Qr3viR5` | +| **Policy** | `readwrite` | +| **Bucket** | `nuc-portal-previews` | + +--- + +## Port Forwarder + +MinIO container wasn't exposed on host. Created port forwarder: + +```bash +# Container: minio-port-fwd +# Forwards: 9000 (API) and 9001 (Console) +docker run -d --name minio-port-fwd \ + --network xwowg8kswwsocssgocs8ss40 \ + -p 9000:9000 \ + -p 9001:9001 \ + alpine/socat \ + TCP-LISTEN:9000,fork,reuseaddr TCP-CONNECT:minio-xwowg8kswwsocssgocs8ss40:9000 +``` + +--- + +## Environment Variables + +Added to `/Users/agutierrez/Desktop/nuc/nuc-portal/.env.local`: + +```env +# MinIO / S3 Storage (for deployment previews) +S3_ENDPOINT=http://192.168.1.3:9000 +S3_ACCESS_KEY=nuc-portal +S3_SECRET_KEY=YpVhIltqY6itWQXHWbEzJ82O9Qr3viR5 +S3_BUCKET=nuc-portal-previews +S3_REGION=us-east-1 +``` + +--- + +## Files Created + +### `src/lib/s3.ts` + +S3 client helper with functions: + +| Function | Purpose | +|----------|---------| +| `uploadFile(key, body, contentType)` | Upload any file | +| `uploadPreviewScreenshot(appUuid, deploymentUuid, buffer)` | Upload deployment preview | +| `getPresignedUrl(key, expiresIn)` | Get signed URL for reading | +| `getPreviewUrl(appUuid, deploymentUuid)` | Get preview presigned URL | +| `fileExists(key)` | Check if file exists | +| `previewExists(appUuid, deploymentUuid)` | Check if preview exists | +| `deleteFile(key)` | Delete a file | +| `getFile(key)` | Download file as Buffer | + +### `src/app/api/deployments/[uuid]/preview/route.ts` + +API endpoint that: +- Checks if preview exists in S3 +- Returns presigned URL (valid 1 hour) if exists +- Returns `{ exists: false }` with hint if not + +--- + +## Dashboard Integration + +Updated `DeploymentDashboard.tsx`: +- Added SWR hook for preview fetching +- Shows loading spinner while fetching +- Displays image if preview exists +- Falls back to placeholder if not + +--- + +## Storage Structure + +``` +nuc-portal-previews/ +└── previews/ + └── {app-uuid}/ + └── {deployment-uuid}.png +``` + +--- + +## Dependencies Added + +```json +{ + "@aws-sdk/client-s3": "^3.x", + "@aws-sdk/s3-request-presigner": "^3.x" +} +``` + +--- + +## Next Steps + +To capture screenshots automatically: +1. Add post-deployment hook in Coolify +2. Use Playwright (`playwriter-nuc-01`) to take screenshot +3. Upload to MinIO via `uploadPreviewScreenshot()` + +Manual capture example: +```typescript +// Using Playwright to capture screenshot +const screenshot = await page.screenshot({ type: 'png' }); +await uploadPreviewScreenshot(appUuid, deploymentUuid, screenshot); +``` + +--- + +## Verification + +```bash +# Test MinIO health +curl http://192.168.1.3:9000/minio/health/live + +# List buckets (via mc) +ssh nuc 'docker run --rm --network host --entrypoint /bin/sh minio/mc -c " +mc alias set m http://localhost:9000 nuc-portal YpVhIltqY6itWQXHWbEzJ82O9Qr3viR5 +mc ls m/ +"' + +# Test preview API +curl http://localhost:3000/api/deployments//preview +``` + +--- + +## Related + +- MinIO container: `minio-xwowg8kswwsocssgocs8ss40` +- Port forwarder: `minio-port-fwd` +- Implementation: `.artifacts/2026-02-06_19-30_deployment-dashboard-implementation.md`