This project provides a lightweight, high-performance proxy server written in Rust. It exposes an OpenAI-compatible API endpoint (/v1/chat/completions) and intelligently routes requests to the Google Gemini API. It manages a pool of Gemini API keys, rotating them for each request to distribute the load and manage API quotas effectively.
The entire application is containerized with Docker for easy, one-click deployment.
PS: The entire application is generated by Claude Code except this line, feel free to use it.
- OpenAI API Compatibility: Drop-in replacement for services that use the OpenAI Chat Completions API format.
- API Key Management: Dynamic creation, editing, and deletion of API keys with usage tracking.
- Web Management Interface: Modern, tech-styled web dashboard for managing API keys and monitoring usage.
- Usage Analytics: Real-time tracking of requests, input/output tokens, and API key statistics.
- Secure Authentication: JWT-based admin authentication with role-based access control.
- API Key Rotation: Automatically rotates Gemini API keys from a predefined pool on each request.
- Dynamic Model Selection: Uses the
modelfield from the request payload to target different Gemini models (e.g.,gemini-1.5-flash,gemini-1.5-pro). - High Performance: Built with Rust and Axum for asynchronous, fast, and reliable performance.
- Easy Deployment: One-command deployment using Docker and a simple shell script.
- Database Storage: SQLite database for persistent storage of API keys and usage logs.
git clone https://github.com/cod3vil/gemini-pool.git
cd gemini-poolThe application requires a .env file to store your Gemini API keys.
-
Create the
.envfile by copying the provided example:cp gemini-pool/.env.example gemini-pool/.env
-
Edit
gemini-pool/.envand configure the required settings:# gemini-pool/.env # Put your Gemini API keys here, separated by commas. GEMINI_API_KEYS=your_key_1,your_key_2,your_key_3 # Admin authentication for web management interface ADMIN_USERNAME=admin ADMIN_PASSWORD=your_secure_admin_password # JWT secret for admin session management (change this in production) JWT_SECRET=your_jwt_secret_change_in_production # Database URL (SQLite by default) DATABASE_URL=sqlite:./gemini_pool.db # The address to bind the server to (inside the container). # This must be 0.0.0.0:8080 to be accessible from the host via Docker. LISTEN_ADDR=0.0.0.0:8080
The included deploy.sh script handles everything from building the Docker image to running the container.
-
Make the script executable:
chmod +x deploy.sh
-
Run the script:
- To run on the default port
8080:./deploy.sh
- To run on a custom port (e.g.,
9000):./deploy.sh 9000
- To run on the default port
The script will build the image, stop any old containers, and start a new one in the background.
- To view logs:
docker logs -f gemini-pool-container - To stop the service:
docker stop gemini-pool-container
After deployment, you can access the web management interface to manage API keys and monitor usage:
- Home Page: Navigate to
http://127.0.0.1:8080/- Bilingual (中文/English) features overview with direct links to admin panel - Admin Interface: Access
http://127.0.0.1:8080/admin- Management interface home - Login Page:
http://127.0.0.1:8080/admin/login.html - Management Dashboard:
http://127.0.0.1:8080/admin/management.html - Use your admin credentials (from your
.envfile)
All admin API endpoints are now organized under /admin/api/:
- Authentication:
POST /admin/api/auth/login- Admin loginGET /admin/api/auth/verify- Token verification
- Dashboard:
GET /admin/api/dashboard- Statistics - API Key Management:
GET /admin/api/api-keys- List API keysPOST /admin/api/api-keys- Create API keyGET /admin/api/api-keys/{id}- Get specific API keyPUT /admin/api/api-keys/{id}- Update API keyDELETE /admin/api/api-keys/{id}- Delete API key
- 🎨 Modern Tech-Styled Interface: Cyberpunk-inspired design with matrix rain background effects
- 🌍 Bilingual Support: Complete Chinese/English interface with persistent language preferences
- 📊 Real-time Dashboard: View total API keys, requests, tokens, and active keys
- 🔑 API Key Management:
- Create new API keys (auto-generated or custom)
- Edit key names and toggle active status
- Delete unused keys
- View detailed usage statistics per key
- 📈 Usage Analytics: Track input/output tokens and request counts
- 🔒 Secure Authentication: JWT-based session management
- 📱 Responsive Design: Works on desktop and mobile devices
When using the API endpoints (/v1/chat/completions, /v1/models), clients must include an API key created through the web interface:
curl -X POST http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_client_api_key" \
-d '{...}'Send a POST request to the /v1/chat/completions endpoint. The request body should be in the OpenAI Chat Completions format.
Here is an example using curl to interact with the service. You can specify any supported Gemini model in the model field.
curl -X POST http://127.0.0.1:8080/v1/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer your_client_api_key" \
-d '{
"model": "gemini-1.5-flash",
"messages": [
{
"role": "system",
"content": "You are a helpful assistant."
},
{
"role": "user",
"content": "Hello! What is the capital of China?"
}
]
}'Note: Replace your_client_api_key with an API key created through the web management interface.
The server will forward this request to the Gemini API using one of your keys and return a response in the OpenAI format.
To see the list of available models supported by this proxy, send a GET request to the /v1/models endpoint.
curl -H "Authorization: Bearer your_client_api_key" \
http://127.0.0.1:8080/v1/modelsFor production environments, it's recommended to use nginx as a reverse proxy in front of the Gemini Pool service. This provides additional security, SSL termination, and load balancing capabilities.
Thanks to the reorganized route structure with /admin/api/* paths and a dedicated index page, you can use a very simple nginx configuration:
server {
listen 80;
server_name your-domain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL Configuration
ssl_certificate /path/to/your/fullchain.pem;
ssl_certificate_key /path/to/your/private.key;
# Security Headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
# Proxy all requests to the application
location ^~ / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# For long-running requests
proxy_read_timeout 60s;
client_max_body_size 10M;
}
}