- name
- codex-lb-load-balancer
- description
- ChatGPT/Codex multi-account load balancer with usage tracking, API key management, and OpenAI-compatible proxy
- triggers
- ["set up codex load balancer for multiple accounts","configure chatgpt account pooling","track openai api usage across accounts","manage api keys with rate limits","deploy codex-lb with docker","balance load across multiple chatgpt accounts","set up openai compatible proxy","monitor chatgpt usage and costs"]
# codex-lb Load Balancer
> Skill by [ara.so](https://ara.so) — Codex Skills collection.
## Overview
**codex-lb** is a load balancer and proxy for ChatGPT/Codex accounts that pools multiple OpenAI accounts, tracks usage per account and API key, enforces rate limits, and provides a web dashboard for management. It exposes OpenAI-compatible endpoints (`/v1/*` and `/backend-api/codex/*`) for any client (Codex CLI, OpenCode, OpenClaw, OpenAI SDK).
**Key features:**
- Pool multiple ChatGPT accounts with automatic load balancing
- Per-account usage tracking (tokens, cost, 28-day trends)
- API key management with per-key rate limits (token, cost, time window, model)
- Dashboard with password + optional TOTP authentication
- Auto-sync available models from upstream
- WebSocket support for native Codex streaming
## Installation
### Docker (Recommended)
```bash
docker volume create codex-lb-data
docker run -d --name codex-lb \
-p 2455:2455 -p 1455:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
```
### uvx (Python)
```bash
uvx codex-lb
```
Dashboard: [http://localhost:2455](http://localhost:2455)
Proxy endpoints:
- OpenAI v1: `http://localhost:2455/v1`
- Codex backend: `http://localhost:2455/backend-api/codex`
Health check: `http://localhost:1455/health`
## Configuration
### First-Run Setup (Remote Access)
When accessing the dashboard remotely for the first time, you need a bootstrap token to set the password.
**Auto-generated token** (default):
```bash
docker logs codex-lb
# Look for:
# ============================================
# Dashboard bootstrap token (first-run):
# <token>
# ============================================
```
Open dashboard → enter token + new password → done.
**Manual bootstrap token:**
```bash
docker run -d --name codex-lb \
-e CODEX_LB_DASHBOARD_BOOTSTRAP_TOKEN=your-secret-token \
-p 2455:2455 -p 1455:1455 \
-v codex-lb-data:/var/lib/codex-lb \
ghcr.io/soju06/codex-lb:latest
```
**Local access** (localhost) bypasses bootstrap entirely.
### Adding Accounts
1. Open dashboard → **Accounts** → **Add Account**
2. Paste OpenAI session token or login credentials
3. Account syncs available models automatically
### API Key Authentication
API key auth is **disabled by default**. Enable in **Settings → API Key Auth** when:
- Clients connect remotely
- Running in Docker/VM/container with non-local networking
When enabled, clients must pass a Bearer token:
```http
Authorization: Bearer sk-clb-YOUR_KEY_HERE
```
Create API keys in dashboard → **API Keys** → **Create Key**.
Configure rate limits per key:
- Token limit (per window)
- Cost limit (USD, per window)
- Time window (e.g., 1 hour, 1 day)
- Allowed models
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `CODEX_LB_DASHBOARD_BOOTSTRAP_TOKEN` | auto-generated | Bootstrap token for first-run password setup |
| `CODEX_LB_UPSTREAM_STREAM_TRANSPORT` | `auto` | `auto`, `websocket`, or `http` for Codex streaming |
| `CODEX_LB_UPSTREAM_WEBSOCKET_TRUST_ENV` | `false` | Use environment proxies for WebSocket handshakes |
| `CODEX_LB_DATA_DIR` | `/var/lib/codex-lb` | Data directory for SQLite DB and state |
## Client Configuration
### Codex CLI
`~/.codex/config.toml`:
```toml
model = "gpt-5.3-codex"
model_reasoning_effort = "xhigh"
model_provider = "codex-lb"
[model_providers.codex-lb]
name = "OpenAI"
base_url = "http://127.0.0.1:2455/backend-api/codex"
wire_api = "responses"
supports_websockets = true
requires_openai_auth = true
```
**With API key auth:**
```toml
[model_providers.codex-lb]
name = "OpenAI"
base_url = "http://127.0.0.1:2455/backend-api/codex"
wire_api = "responses"
env_key = "CODEX_LB_API_KEY"
supports_websockets = true
requires_openai_auth = true
```
```bash
export CODEX_LB_API_KEY="sk-clb-..."
codex
```
**Enable native WebSocket streaming:**
```bash
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=websocket
```
**Verify WebSocket transport:**
```bash
RUST_LOG=debug codex exec "Reply with OK only."
```
Healthy signals:
- CLI logs: `connecting to websocket`, `successfully connected to websocket`
- codex-lb logs: `WebSocket /backend-api/codex/responses`
- No fallback `POST /backend-api/codex/responses`
**Migrate existing sessions from OpenAI provider:**
```bash
# JSONL session files
find ~/.codex/sessions -name '*.jsonl' \
-exec sed -i '' 's/"model_provider":"openai"/"model_provider":"codex-lb"/g' {} +
# SQLite state DB (>= v0.105.0)
sqlite3 ~/.codex/state_5.sqlite \
"UPDATE threads SET model_provider = 'codex-lb' WHERE model_provider = 'openai';"
```
### OpenCode
**Important:** Use the built-in `openai` provider with `baseURL` override. Custom providers with `@ai-sdk/openai-compatible` drop reasoning content.
Clear existing OpenAI credentials:
```bash
jq 'del(.openai)' ~/.local/share/opencode/auth.json > auth.json.tmp && mv auth.json.tmp ~/.local/share/opencode/auth.json
```
`~/.config/opencode/opencode.json`:
```json
{
"$schema": "https://opencode.ai/config.json",
"provider": {
"openai": {
"options": {
"baseURL": "http://127.0.0.1:2455/v1",
"apiKey": "{env:CODEX_LB_API_KEY}"
},
"models": {
"gpt-5.4": {
"name": "GPT-5.4",
"reasoning": true,
"options": { "reasoningEffort": "high", "reasoningSummary": "detailed" },
"limit": { "context": 1050000, "output": 128000 }
},
"gpt-5.3-codex": {
"name": "GPT-5.3 Codex",
"reasoning": true,
"options": { "reasoningEffort": "high", "reasoningSummary": "detailed" },
"limit": { "context": 272000, "output": 65536 }
}
}
}
},
"model": "openai/gpt-5.3-codex"
}
```
```bash
export CODEX_LB_API_KEY="sk-clb-..."
opencode
```
### OpenClaw
`~/.openclaw/openclaw.json`:
```json
{
"agents": {
"defaults": {
"model": { "primary": "codex-lb/gpt-5.4" },
"models": {
"codex-lb/gpt-5.4": { "params": { "cacheRetention": "short" } },
"codex-lb/gpt-5.3-codex": { "params": { "cacheRetention": "short" } }
}
}
},
"models": {
"mode": "merge",
"providers": {
"codex-lb": {
"baseUrl": "http://127.0.0.1:2455/v1",
"apiKey": "${CODEX_LB_API_KEY}",
"api": "openai-responses",
"models": [
{
"id": "gpt-5.4",
"name": "gpt-5.4 (codex-lb)",
"contextWindow": 1050000,
"contextTokens": 272000,
"maxTokens": 4096,
"input": ["text"],
"reasoning": false
},
{
"id": "gpt-5.3-codex",
"name": "gpt-5.3-codex (codex-lb)",
"contextWindow": 400000,
"contextTokens": 272000,
"maxTokens": 4096,
"input": ["text"],
"reasoning": false
}
]
}
}
}
}
```
```bash
export CODEX_LB_API_KEY="sk-clb-..."
```
### OpenAI Python SDK
```python
from openai import OpenAI
client = OpenAI(
base_url="http://127.0.0.1:2455/v1",
api_key=os.environ["CODEX_LB_API_KEY"], # or "dummy" if auth disabled
)
response = client.chat.completions.create(
model="gpt-5.3-codex",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)
```
### Any OpenAI-Compatible Client
Point the base URL to:
- Chat Completions API: `http://127.0.0.1:2455/v1`
- Codex Backend API: `http://127.0.0.1:2455/backend-api/codex`
Pass API key as `Authorization: Bearer sk-clb-...` header if auth is enabled.
## Usage Patterns
### Multi-Account Load Balancing
codex-lb automatically distributes requests across healthy accounts based on:
- Account availability
- Usage limits
- Model availability per account
Add accounts in dashboard → **Accounts** → **Add Account**. Disable individual accounts temporarily without removing them.
### Rate Limiting
Configure per-API-key limits in dashboard → **API Keys** → **Edit Key**:
**Token limit:**
```
Max tokens: 100000
Window: 1 hour
```
**Cost limit:**
```
Max cost: 5.00 USD
Window: 1 day
```
**Model restrictions:**
```
Allowed models: gpt-5.3-codex, gpt-5.4-mini
```
### Usage Tracking
Dashboard → **Accounts** shows per-account:
- Total tokens used
- Total cost (USD)
- 28-day usage trends
- Model availability
Dashboard → **API Keys** shows per-key:
- Requests made
- Tokens consumed
- Cost incurred
- Rate limit status
### WebSocket Streaming (Codex)
codex-lb supports native WebSocket streaming for Codex CLI:
**Auto mode (default):**
```bash
# Uses WebSocket for native Codex headers or preferred models
# Falls back to HTTP for others
```
**Force WebSocket:**
```bash
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=websocket
```
**Force HTTP:**
```bash
export CODEX_LB_UPSTREAM_STREAM_TRANSPORT=http
```
**Reverse proxy setup** — ensure your reverse proxy forwards WebSocket upgrades:
**nginx:**
```nginx
location / {
proxy_pass http://codex-lb:2455;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
```
**Caddy:**
```
reverse_proxy localhost:2455
```
GitHub에서 보기