292 lines
7.2 KiB
Markdown
292 lines
7.2 KiB
Markdown
# MinIO Setup Technical Specification
|
|
|
|
## Project Status
|
|
|
|
Starting MinIO integration from scratch. Previous implementation had compatibility issues with bucket policies in SNSD mode. New implementation uses SNMD (Single Node Multi Drive) configuration with presigned URLs for reliable file access.
|
|
|
|
## Architecture Overview
|
|
|
|
### Storage Strategy
|
|
|
|
- **Mode**: SNMD (4 virtual drives) for full S3 compatibility
|
|
- **Access Method**: Presigned URLs only (no bucket policies)
|
|
- **Bucket Structure**: Single bucket `banatie` with path-based organization
|
|
- **File Organization**: `orgId/projectId/category/year-month/filename`
|
|
|
|
### Technology Stack
|
|
|
|
- MinIO latest (`quay.io/minio/minio:latest`)
|
|
- Docker Compose for orchestration
|
|
- PostgreSQL for application data
|
|
- Express.js API with TypeScript
|
|
|
|
## Configuration Files Status
|
|
|
|
### Completed Files
|
|
|
|
- `docker-compose.yml` - SNMD configuration with 4 virtual drives
|
|
- `.env.docker` - Environment variables for development
|
|
- `src/services/MinioStorageService.ts` - Updated service implementation
|
|
- `src/services/StorageFactory.ts` - Service factory configuration
|
|
- `src/routes/images.ts` - Presigned URL endpoints
|
|
|
|
### Integration Requirements
|
|
|
|
#### 1. Update Application Router
|
|
|
|
Add images router to main application in `src/app.ts`:
|
|
|
|
```typescript
|
|
import { imagesRouter } from './routes/images';
|
|
|
|
// Add to routes section
|
|
app.use('/api', imagesRouter);
|
|
```
|
|
|
|
#### 2. Environment Variables Update
|
|
|
|
Update existing `.env` file with MinIO configuration:
|
|
|
|
```bash
|
|
# Add to existing .env file
|
|
MINIO_ROOT_USER=banatie_admin
|
|
MINIO_ROOT_PASSWORD=banatie_storage_secure_key_2024
|
|
STORAGE_TYPE=minio
|
|
MINIO_ENDPOINT=minio:9000
|
|
MINIO_ACCESS_KEY=banatie_service
|
|
MINIO_SECRET_KEY=banatie_service_key_2024
|
|
MINIO_USE_SSL=false
|
|
MINIO_BUCKET_NAME=banatie
|
|
MINIO_PUBLIC_URL=http://localhost:9000
|
|
API_BASE_URL=http://localhost:3000
|
|
DEFAULT_ORG_ID=default
|
|
DEFAULT_PROJECT_ID=main
|
|
DEFAULT_USER_ID=system
|
|
PRESIGNED_URL_EXPIRY=86400
|
|
```
|
|
|
|
#### 3. Database Script Update
|
|
|
|
Update `scripts/init-db.sql` to use new database name `banatie` instead of previous naming.
|
|
|
|
#### 4. Service Dependencies Update
|
|
|
|
Update existing image generation services to use new storage configuration:
|
|
|
|
```typescript
|
|
// In ImageGenService.ts or similar
|
|
const storageService = StorageFactory.getInstance();
|
|
const uploadResult = await storageService.uploadFile(
|
|
orgId,
|
|
projectId,
|
|
'generated',
|
|
filename,
|
|
buffer,
|
|
'image/png',
|
|
);
|
|
// Use uploadResult.url (returns API URL for presigned access)
|
|
```
|
|
|
|
## Setup Instructions
|
|
|
|
### 1. Directory Structure
|
|
|
|
Create required directories:
|
|
|
|
```bash
|
|
mkdir -p data/storage/{drive1,drive2,drive3,drive4}
|
|
mkdir -p data/postgres
|
|
```
|
|
|
|
### 2. Service Startup
|
|
|
|
```bash
|
|
# Start all services
|
|
docker-compose up -d
|
|
|
|
# Verify services are healthy
|
|
docker-compose ps
|
|
|
|
# Check MinIO logs
|
|
docker logs banatie-storage
|
|
|
|
# Check initialization logs
|
|
docker logs banatie-storage-init
|
|
```
|
|
|
|
### 3. Verification Steps
|
|
|
|
#### MinIO Console Access
|
|
|
|
- URL: http://localhost:9001
|
|
- Username: banatie_admin
|
|
- Password: banatie_storage_secure_key_2024
|
|
|
|
#### Test Presigned URL Generation
|
|
|
|
```bash
|
|
# Test image upload endpoint
|
|
curl -X POST http://localhost:3000/api/upload \
|
|
-F "files=@test.png" \
|
|
-F "category=generated"
|
|
|
|
# Test presigned URL access
|
|
curl -I "http://localhost:3000/api/images/default/main/generated/test-image.png"
|
|
# Should return 302 redirect to presigned URL
|
|
```
|
|
|
|
#### Verify SNMD Mode
|
|
|
|
```bash
|
|
# Check MinIO is in erasure coding mode
|
|
docker exec banatie-storage mc admin info local
|
|
# Should show 4 drives and erasure coding information
|
|
```
|
|
|
|
## Integration Testing
|
|
|
|
### Required Tests
|
|
|
|
1. **Storage Service Initialization**
|
|
- Verify StorageFactory creates MinioStorageService
|
|
- Confirm bucket creation and accessibility
|
|
|
|
2. **File Upload/Download Cycle**
|
|
- Upload file via StorageService
|
|
- Generate presigned URL
|
|
- Verify file accessibility via presigned URL
|
|
|
|
3. **API Endpoint Testing**
|
|
- Test `/api/images/:orgId/:projectId/:category/:filename`
|
|
- Verify 302 redirect to presigned URL
|
|
- Test fallback direct streaming
|
|
|
|
4. **Error Handling**
|
|
- Test invalid file paths
|
|
- Test expired presigned URLs
|
|
- Test MinIO connection failures
|
|
|
|
### Test Script Template
|
|
|
|
```bash
|
|
#!/bin/bash
|
|
# test-minio-integration.sh
|
|
|
|
echo "Testing MinIO Integration"
|
|
|
|
# Test 1: Upload file
|
|
UPLOAD_RESPONSE=$(curl -s -X POST http://localhost:3000/api/upload \
|
|
-F "files=@test.png" \
|
|
-F "category=generated")
|
|
|
|
echo "Upload Response: $UPLOAD_RESPONSE"
|
|
|
|
# Extract URL from response
|
|
FILE_URL=$(echo "$UPLOAD_RESPONSE" | jq -r '.files[0].url')
|
|
|
|
# Test 2: Access via presigned URL
|
|
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" "$FILE_URL")
|
|
|
|
if [ "$HTTP_CODE" = "302" ]; then
|
|
echo "SUCCESS: Presigned URL redirect working"
|
|
else
|
|
echo "FAILURE: Expected 302, got $HTTP_CODE"
|
|
fi
|
|
```
|
|
|
|
## Production Considerations
|
|
|
|
### Environment Differences
|
|
|
|
Development and production use identical configuration with different values:
|
|
|
|
```bash
|
|
# Production .env differences
|
|
API_BASE_URL=https://api.yourdomain.com
|
|
MINIO_PUBLIC_URL=https://storage.yourdomain.com:9000
|
|
MINIO_USE_SSL=true
|
|
```
|
|
|
|
### Security Notes
|
|
|
|
- All passwords use environment variables (no hardcoded values)
|
|
- Presigned URLs expire after 24 hours by default
|
|
- Service user has minimal required permissions
|
|
- MinIO admin access separate from application access
|
|
|
|
### Scaling Path
|
|
|
|
- Current SNMD setup supports development and small production loads
|
|
- Can migrate to distributed MinIO cluster when needed
|
|
- Presigned URL architecture remains unchanged during scaling
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
1. **403 Errors**: Check presigned URL generation and MinIO service user permissions
|
|
2. **404 Errors**: Verify file paths and bucket configuration
|
|
3. **Connection Errors**: Confirm MinIO service health and network connectivity
|
|
|
|
### Debug Commands
|
|
|
|
```bash
|
|
# Check MinIO health
|
|
docker exec banatie-storage mc admin info local
|
|
|
|
# List bucket contents
|
|
docker exec banatie-storage mc ls storage/banatie --recursive
|
|
|
|
# Check service logs
|
|
docker logs banatie-storage
|
|
docker logs banatie-app
|
|
```
|
|
|
|
### Recovery Procedures
|
|
|
|
```bash
|
|
# Reset MinIO data (development only)
|
|
docker-compose down
|
|
rm -rf data/storage/*
|
|
docker-compose up -d
|
|
|
|
# Recreate bucket structure
|
|
docker exec banatie-storage mc mb storage/banatie
|
|
```
|
|
|
|
## Implementation Priority
|
|
|
|
### Phase 1 (Immediate)
|
|
|
|
1. Update app.ts with images router
|
|
2. Update environment configuration
|
|
3. Test basic upload/download functionality
|
|
|
|
### Phase 2 (Next)
|
|
|
|
1. Update existing image generation services
|
|
2. Implement comprehensive error handling
|
|
3. Add integration tests
|
|
|
|
### Phase 3 (Future)
|
|
|
|
1. Add monitoring and logging
|
|
2. Implement file cleanup policies
|
|
3. Add CDN integration capability
|
|
|
|
## Acceptance Criteria
|
|
|
|
Integration is complete when:
|
|
|
|
- [ ] All services start successfully via docker-compose
|
|
- [ ] MinIO operates in SNMD mode with 4 drives
|
|
- [ ] Image upload returns API URL format
|
|
- [ ] API URLs redirect to working presigned URLs
|
|
- [ ] Generated images accessible via presigned URLs
|
|
- [ ] Error handling provides meaningful responses
|
|
- [ ] Integration tests pass consistently
|
|
|
|
## Notes
|
|
|
|
This implementation prioritizes simplicity and reliability over advanced features. The presigned URL approach ensures consistent behavior across different MinIO configurations and provides a foundation for future enhancements without requiring architectural changes.
|