# 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`