A secure proxy server for Google Generative AI APIs with Supabase authentication, rate limiting, and usage tracking.
- 🔐 Supabase Authentication: JWT-based authentication for secure access
- 🚦 Rate Limiting: User-specific rate limits based on subscription tiers
- 📊 Usage Tracking: Comprehensive token and cost tracking
- 💰 Cost Management: Real-time cost calculation and daily limits
- 🔒 Security: Helmet.js security headers, CORS configuration
- 📈 Logging: Structured logging with Winston
- 🐳 Containerized: Docker support for easy deployment
- ☁️ Cloud Ready: Optimized for Google Cloud Run deployment
[Electron App] → [Proxy Server] → [Google Gemini API]
↓
[Supabase Database]
The proxy server:
- Authenticates users via Supabase JWT tokens
- Checks rate limits and usage quotas
- Forwards requests to Google Gemini API
- Tracks usage and costs in Supabase
- Returns responses with usage metadata
- Node.js 18+
- Docker (for containerization)
- Google Cloud SDK (for deployment)
- Supabase account and project
- Google Cloud project with Gemini API access
-
Clone and install dependencies:
git clone <repository-url> cd percepteye-proxy npm install
-
Set up environment:
cp env.example .env # Edit .env with your actual values -
Start development server:
npm run dev
-
Test the server:
curl http://localhost:3000/health
Required environment variables:
# Server Configuration
PORT=3000
NODE_ENV=development
LOG_LEVEL=info
CORS_ORIGIN=*
# Supabase Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_ANON_KEY=your-anon-key
SUPABASE_SERVICE_ROLE=your-service-role-key
# Google Cloud Configuration
GCP_PROJECT_ID=your-gcp-project-id
GCP_REGION=us-central1
SERVICE_NAME=gemini-proxy
# Gemini API Configuration
GEMINI_API_KEY=your-gemini-api-keyAll API endpoints (except /health and /api/docs) require authentication via Bearer token:
Authorization: Bearer <supabase-jwt-token>| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Service health check |
| GET | /api/docs |
API documentation |
| GET | /api/gemini/models |
List available models |
| GET | /api/gemini/usage |
Get user usage statistics |
| GET | /api/gemini/health |
Gemini service health |
| POST | /api/gemini/:model/generateContent |
Generate content |
| POST | /api/gemini/:model/streamGenerateContent |
Stream generate content |
| POST | /api/gemini/:model/countTokens |
Count tokens |
gemini-progemini-pro-visiongemini-1.5-progemini-1.5-flashgemini-1.5-flash-8b
Generate Content:
curl -X POST "https://your-proxy-url/api/gemini/gemini-pro/generateContent" \
-H "Authorization: Bearer <your-jwt-token>" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"parts": [{
"text": "Explain quantum computing in simple terms"
}]
}]
}'Get Usage Statistics:
curl -X GET "https://your-proxy-url/api/gemini/usage" \
-H "Authorization: Bearer <your-jwt-token>"The proxy uses the following Supabase tables:
Tracks API usage per user:
user_id: User identifiertokens_used: Number of tokens consumedcost: Cost in USDmodel_name: Gemini model usedrequest_type: Type of request (generate, stream, etc.)timestamp: Request timestamp
Defines user-specific limits:
user_id: User identifierrequests_per_hour: Hourly request limittokens_per_day: Daily token limitmax_cost_per_day: Daily cost limit
User profile information:
user_id: User identifiersubscription_tier: User's subscription levelis_active: Account status
The proxy implements multiple levels of rate limiting:
- Global Rate Limit: 1000 requests per 15 minutes per IP
- User-based Limits: Based on subscription tier:
- Free: 100 requests/hour
- Pro: 1000 requests/hour
- Premium: 5000 requests/hour
- Enterprise: 10000 requests/hour
- Token Limits: Daily token consumption limits
- Cost Limits: Daily spending limits
-
Prepare environment:
cp env.example .env # Edit .env with production values -
Run deployment:
./deploy.sh
-
Build and push image:
docker build -t gcr.io/PROJECT_ID/gemini-proxy . docker push gcr.io/PROJECT_ID/gemini-proxy -
Deploy to Cloud Run:
gcloud run deploy gemini-proxy \ --image gcr.io/PROJECT_ID/gemini-proxy \ --region us-central1 \ --allow-unauthenticated \ --set-env-vars "NODE_ENV=production,..."
gcloud builds submit --config cloudbuild.yaml- Service health:
/health - Gemini service health:
/api/gemini/health
The service uses structured logging with different levels:
error: Error conditionswarn: Warning conditionsinfo: Informational messagesdebug: Debug information
Logs are output to console in JSON format for production.
Monitor these key metrics:
- Request rate and latency
- Error rates by endpoint
- Token usage per user
- Cost accumulation
- Rate limit hits
The proxy implements security best practices:
- Helmet.js for security headers
- CORS configuration
- Request size limits
- Rate limiting
- Input validation with Joi
- JWT token validation via Supabase
- User session management
- Role-based access control
- No sensitive data logged
- API keys masked in logs
- Secure environment variable handling
In your Electron app, use Supabase client to authenticate:
import { createClient } from '@supabase/supabase-js'
const supabase = createClient(
'https://bvhsrithcvbzoeogcbyb.supabase.co',
'your-anon-key'
)
// After user login
const { data: { session } } = await supabase.auth.getSession()
const token = session?.access_tokenUse the JWT token to call the proxy:
const response = await fetch('https://your-proxy-url/api/gemini/gemini-pro/generateContent', {
method: 'POST',
headers: {
'Authorization': `Bearer ${token}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({
contents: [{
parts: [{ text: 'Your prompt here' }]
}]
})
})src/
├── config/ # Configuration files
├── middleware/ # Express middleware
├── routes/ # API routes
├── services/ # Business logic services
├── utils/ # Utility functions
└── server.js # Main server file
npm start: Start production servernpm run dev: Start development server with nodemonnpm test: Run tests
- Create middleware in
src/middleware/ - Add routes in
src/routes/ - Implement business logic in
src/services/ - Add tests
- Update documentation
- Authentication errors: Check Supabase configuration and JWT token validity
- Rate limiting: Monitor usage and adjust limits in database
- API errors: Check Gemini API key and quota
- Connection issues: Verify network connectivity and firewall rules
Set LOG_LEVEL=debug for detailed logging:
LOG_LEVEL=debug npm run devUse health endpoints to diagnose issues:
- Service:
GET /health - Gemini API:
GET /api/gemini/health
For issues and questions:
- Check the logs for error details
- Verify environment configuration
- Test with health endpoints
- Check Supabase database connectivity
MIT License - see LICENSE file for details. # percept-eye-proxy