gpt2api-openai-gateway

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

gpt2api OpenAI Gateway

gpt2api OpenAI 网关

Skill by ara.so — Daily 2026 Skills collection.
gpt2api
is a self-hosted OpenAI-compatible API gateway that reverse-engineers
chatgpt.com
to expose GPT Image 2 / DALL·E 3 / IMG2 grayscale capabilities via standard
/v1/images/generations
,
/v1/images/edits
, and
/v1/chat/completions
endpoints. It provides multi-account pooling, proxy pooling, rate limiting, credit billing, and an admin dashboard.

ara.so 开发的Skill — 每日2026技能合集。
gpt2api
是一款自托管的兼容OpenAI的API网关,通过逆向工程
chatgpt.com
,将GPT Image 2 / DALL·E 3 / IMG2灰度图生成能力通过标准的
/v1/images/generations
/v1/images/edits
/v1/chat/completions
端点暴露出来。它支持多账号池、代理池、速率限制、信用计费以及管理控制台。

Installation & Deployment

安装与部署

Docker Compose (Recommended)

Docker Compose(推荐)

bash
git clone https://github.com/432539/gpt2api.git
cd gpt2api/deploy
cp .env.example .env
Edit
.env
— these three are required:
env
JWT_SECRET=<generate with: openssl rand -base64 48 | tr -d '=/+' | cut -c1-48>
CRYPTO_AES_KEY=<generate with: openssl rand -hex 32>
MYSQL_ROOT_PASSWORD=<strong-password>
MYSQL_PASSWORD=<strong-password>
Generate secrets:
bash
undefined
bash
git clone https://github.com/432539/gpt2api.git
cd gpt2api/deploy
cp .env.example .env
编辑
.env
文件 — 以下三项为必填项:
env
JWT_SECRET=<使用以下命令生成: openssl rand -base64 48 | tr -d '=/+' | cut -c1-48>
CRYPTO_AES_KEY=<使用以下命令生成: openssl rand -hex 32>
MYSQL_ROOT_PASSWORD=<强密码>
MYSQL_PASSWORD=<强密码>
生成密钥:
bash
undefined

CRYPTO_AES_KEY (must be exactly 64 hex chars = 32 bytes AES-256)

CRYPTO_AES_KEY(必须恰好64个十六进制字符 = 32字节AES-256)

openssl rand -hex 32
openssl rand -hex 32

JWT_SECRET (>=32 chars)

JWT_SECRET(≥32个字符)

openssl rand -base64 48 | tr -d '=/+' | cut -c1-48

Start services:

```bash
docker compose up -d --build
docker compose logs -f server
On startup the server automatically:
  1. Waits for MySQL health check
  2. Runs
    goose up
    database migrations
  3. Starts HTTP on
    :8080
Default admin credentials (change immediately):
  • URL:
    http://<server-ip>:8080/
  • Email:
    admin@example.com
  • Password:
    admin123

openssl rand -base64 48 | tr -d '=/+' | cut -c1-48

启动服务:

```bash
docker compose up -d --build
docker compose logs -f server
启动时服务器会自动执行以下操作:
  1. 等待MySQL健康检查通过
  2. 运行
    goose up
    数据库迁移
  3. :8080
    端口启动HTTP服务
默认管理员凭据(请立即修改):
  • 地址:
    http://<服务器IP>:8080/
  • 邮箱:
    admin@example.com
  • 密码:
    admin123

Configuration

配置

Main config file:
configs/config.yaml
(override with
GPT2API_*
env vars in Docker).
yaml
app:
  listen: ":8080"
  base_url: "https://your-domain.com"   # used for signed image proxy URLs

mysql:
  dsn: "user:pass@tcp(mysql:3306)/gpt2api?parseTime=true"
  max_open_conns: 500

redis:
  addr: "redis:6379"
  pool_size: 500                          # needed for distributed locks & rate limiting

jwt:
  secret: "${JWT_SECRET}"
  access_ttl_sec: 7200
  refresh_ttl_sec: 604800

crypto:
  aes_key: "${CRYPTO_AES_KEY}"           # 64-char hex, encrypts account AT/cookies

scheduler:
  min_interval_sec: 10                   # minimum seconds between uses of same account
  daily_usage_ratio: 0.8                 # daily usage cap ratio before circuit break
  cooldown_429_sec: 300                  # backoff when upstream returns 429
Environment variable override pattern (Docker):
env
GPT2API_APP_BASE_URL=https://api.example.com
GPT2API_SCHEDULER_MIN_INTERVAL_SEC=15
GPT2API_SCHEDULER_COOLDOWN_429_SEC=600

主配置文件:
configs/config.yaml
(可通过Docker中的
GPT2API_*
环境变量覆盖)。
yaml
app:
  listen: ":8080"
  base_url: "https://your-domain.com"   # 用于生成签名图片代理URL

mysql:
  dsn: "user:pass@tcp(mysql:3306)/gpt2api?parseTime=true"
  max_open_conns: 500

redis:
  addr: "redis:6379"
  pool_size: 500                          # 分布式锁和速率限制所需

jwt:
  secret: "${JWT_SECRET}"
  access_ttl_sec: 7200
  refresh_ttl_sec: 604800

crypto:
  aes_key: "${CRYPTO_AES_KEY}"           # 64字符十六进制字符串,用于加密账号AT/cookies

scheduler:
  min_interval_sec: 10                   # 同一账号两次使用的最小间隔秒数
  daily_usage_ratio: 0.8                 # 达到每日限额的该比例后触发熔断
  cooldown_429_sec: 300                  # 上游返回429错误后的冷却时间
环境变量覆盖规则(Docker):
env
GPT2API_APP_BASE_URL=https://api.example.com
GPT2API_SCHEDULER_MIN_INTERVAL_SEC=15
GPT2API_SCHEDULER_COOLDOWN_429_SEC=600

Quick Start: First Image Generation

快速开始:首次图片生成

1. Add a Proxy

1. 添加代理

Via admin dashboard → Proxy Management → New Proxy, or via API:
bash
curl -X POST http://localhost:8080/api/admin/proxies \
  -H "Authorization: Bearer $ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "proxy-us-01",
    "url": "http://user:pass@proxy.example.com:8080",
    "type": "http"
  }'
SOCKS5 example:
bash
-d '{"name":"socks-01","url":"socks5://user:pass@proxy.example.com:1080","type":"socks5"}'
通过管理控制台 → 代理管理 → 新增代理,或通过API:
bash
curl -X POST http://localhost:8080/api/admin/proxies \
  -H "Authorization: Bearer $ADMIN_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "proxy-us-01",
    "url": "http://user:pass@proxy.example.com:8080",
    "type": "http"
  }'
SOCKS5示例:
bash
-d '{"name":"socks-01","url":"socks5://user:pass@proxy.example.com:1080","type":"socks5"}'

2. Import ChatGPT Accounts

2. 导入ChatGPT账号

Batch import via admin dashboard → GPT Accounts → Batch Import.
Supported formats — JSON session:
json
[
  {
    "email": "user@example.com",
    "access_token": "$CHATGPT_ACCESS_TOKEN",
    "refresh_token": "$CHATGPT_REFRESH_TOKEN",
    "proxy_id": 1
  }
]
Or AT/RT/ST plain text (one per line in the UI).
通过管理控制台 → GPT账号 → 批量导入。
支持的格式 — JSON会话:
json
[
  {
    "email": "user@example.com",
    "access_token": "$CHATGPT_ACCESS_TOKEN",
    "refresh_token": "$CHATGPT_REFRESH_TOKEN",
    "proxy_id": 1
  }
]
或AT/RT/ST纯文本(UI中每行一个)。

3. Create an API Key

3. 创建API密钥

Admin dashboard → User Management → select user → API Keys → Create Key.
Or programmatically:
bash
curl -X POST http://localhost:8080/api/user/apikeys \
  -H "Authorization: Bearer $USER_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-app-key",
    "rpm_limit": 60,
    "daily_quota": 1000,
    "model_whitelist": ["gpt-image-2", "picture_v2"]
  }'
管理控制台 → 用户管理 → 选择用户 → API密钥 → 创建密钥。
或通过编程方式:
bash
curl -X POST http://localhost:8080/api/user/apikeys \
  -H "Authorization: Bearer $USER_JWT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "my-app-key",
    "rpm_limit": 60,
    "daily_quota": 1000,
    "model_whitelist": ["gpt-image-2", "picture_v2"]
  }'

4. Generate an Image

4. 生成图片

bash
curl -X POST http://localhost:8080/v1/images/generations \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "A serene mountain lake at sunset, photorealistic",
    "n": 2,
    "size": "1024x1024"
  }'
Response:
json
{
  "created": 1713456789,
  "data": [
    {
      "url": "https://your-domain.com/p/img/task123/0?exp=1713460389&sig=abc123"
    },
    {
      "url": "https://your-domain.com/p/img/task123/1?exp=1713460389&sig=def456"
    }
  ]
}

bash
curl -X POST http://localhost:8080/v1/images/generations \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-image-2",
    "prompt": "A serene mountain lake at sunset, photorealistic",
    "n": 2,
    "size": "1024x1024"
  }'
响应:
json
{
  "created": 1713456789,
  "data": [
    {
      "url": "https://your-domain.com/p/img/task123/0?exp=1713460389&sig=abc123"
    },
    {
      "url": "https://your-domain.com/p/img/task123/1?exp=1713460389&sig=def456"
    }
  ]
}

API Reference

API参考

Image Generation

图片生成

POST /v1/images/generations
json
{
  "model": "gpt-image-2",      // or "picture_v2" for IMG2 grayscale
  "prompt": "your prompt",
  "n": 1,                       // number of images (1-4 recommended)
  "size": "1024x1024",          // "1024x1024" | "1792x1024" | "1024x1792"
  "response_format": "url"      // "url" | "b64_json"
}
POST /v1/images/generations
json
{
  "model": "gpt-image-2",      // 或使用"picture_v2"生成IMG2灰度图
  "prompt": "your prompt",
  "n": 1,                       // 图片数量(推荐1-4)
  "size": "1024x1024",          // "1024x1024" | "1792x1024" | "1024x1792"
  "response_format": "url"      // "url" | "b64_json"
}

Image Edit (img2img)

图片编辑(img2img)

POST /v1/images/edits
Content-Type: multipart/form-data
bash
curl -X POST http://localhost:8080/v1/images/edits \
  -H "Authorization: Bearer sk-your-api-key" \
  -F "image=@input.png" \
  -F "prompt=Make the sky more dramatic" \
  -F "model=gpt-image-2" \
  -F "n=1"
POST /v1/images/edits
Content-Type: multipart/form-data
bash
curl -X POST http://localhost:8080/v1/images/edits \
  -H "Authorization: Bearer sk-your-api-key" \
  -F "image=@input.png" \
  -F "prompt=Make the sky more dramatic" \
  -F "model=gpt-image-2" \
  -F "n=1"

Check Task Status

检查任务状态

GET /v1/images/tasks/:id
Authorization: Bearer sk-your-api-key
GET /v1/images/tasks/:id
Authorization: Bearer sk-your-api-key

List Models

列出模型

GET /v1/models
Authorization: Bearer sk-your-api-key
GET /v1/models
Authorization: Bearer sk-your-api-key

Chat Completions (preserved, UI disabled)

聊天补全(已实现,UI入口禁用)

POST /v1/chat/completions
json
{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "Hello"}],
  "stream": true
}

POST /v1/chat/completions
json
{
  "model": "gpt-4o",
  "messages": [{"role": "user", "content": "Hello"}],
  "stream": true
}

Using with OpenAI SDK

与OpenAI SDK配合使用

Python

Python

python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["GPT2API_KEY"],          # your sk- key from the dashboard
    base_url="http://localhost:8080/v1"          # or your production domain
)
python
from openai import OpenAI
import os

client = OpenAI(
    api_key=os.environ["GPT2API_KEY"],          # 从控制台获取的sk-密钥
    base_url="http://localhost:8080/v1"          # 或你的生产域名
)

Single image

单张图片

response = client.images.generate( model="gpt-image-2", prompt="A futuristic city skyline at night, cyberpunk style", n=1, size="1024x1024" ) print(response.data[0].url)
response = client.images.generate( model="gpt-image-2", prompt="A futuristic city skyline at night, cyberpunk style", n=1, size="1024x1024" ) print(response.data[0].url)

Batch images

批量图片

response = client.images.generate( model="gpt-image-2", prompt="Abstract watercolor painting, vibrant colors", n=4, size="1024x1792" # 9:16 portrait ) for img in response.data: print(img.url)
undefined
response = client.images.generate( model="gpt-image-2", prompt="Abstract watercolor painting, vibrant colors", n=4, size="1024x1792" # 9:16竖版 ) for img in response.data: print(img.url)
undefined

Node.js / TypeScript

Node.js / TypeScript

typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.GPT2API_KEY,
  baseURL: process.env.GPT2API_BASE_URL ?? "http://localhost:8080/v1",
});

async function generateImages(prompt: string, count: number = 2) {
  const response = await client.images.generate({
    model: "gpt-image-2",
    prompt,
    n: count,
    size: "1024x1024",
  });
  return response.data.map((img) => img.url);
}

// Image edit
async function editImage(imagePath: string, prompt: string) {
  const fs = await import("fs");
  const response = await client.images.edit({
    image: fs.createReadStream(imagePath),
    prompt,
    model: "gpt-image-2",
  });
  return response.data[0].url;
}
typescript
import OpenAI from "openai";

const client = new OpenAI({
  apiKey: process.env.GPT2API_KEY,
  baseURL: process.env.GPT2API_BASE_URL ?? "http://localhost:8080/v1",
});

async function generateImages(prompt: string, count: number = 2) {
  const response = await client.images.generate({
    model: "gpt-image-2",
    prompt,
    n: count,
    size: "1024x1024",
  });
  return response.data.map((img) => img.url);
}

// 图片编辑
async function editImage(imagePath: string, prompt: string) {
  const fs = await import("fs");
  const response = await client.images.edit({
    image: fs.createReadStream(imagePath),
    prompt,
    model: "gpt-image-2",
  });
  return response.data[0].url;
}

Go

Go

go
package main

import (
    "context"
    "fmt"
    "os"

    openai "github.com/sashabaranov/go-openai"
)

func main() {
    cfg := openai.DefaultConfig(os.Getenv("GPT2API_KEY"))
    cfg.BaseURL = os.Getenv("GPT2API_BASE_URL") // e.g. "http://localhost:8080/v1"
    client := openai.NewClientWithConfig(cfg)

    resp, err := client.CreateImage(context.Background(), openai.ImageRequest{
        Model:  "gpt-image-2",
        Prompt: "A tranquil Japanese garden with cherry blossoms",
        N:      2,
        Size:   openai.CreateImageSize1024x1024,
    })
    if err != nil {
        panic(err)
    }
    for _, img := range resp.Data {
        fmt.Println(img.URL)
    }
}

go
package main

import (
    "context"
    "fmt"
    "os"

    openai "github.com/sashabaranov/go-openai"
)

func main() {
    cfg := openai.DefaultConfig(os.Getenv("GPT2API_KEY"))
    cfg.BaseURL = os.Getenv("GPT2API_BASE_URL") // 例如 "http://localhost:8080/v1"
    client := openai.NewClientWithConfig(cfg)

    resp, err := client.CreateImage(context.Background(), openai.ImageRequest{
        Model:  "gpt-image-2",
        Prompt: "A tranquil Japanese garden with cherry blossoms",
        N:      2,
        Size:   openai.CreateImageSize1024x1024,
    })
    if err != nil {
        panic(err)
    }
    for _, img := range resp.Data {
        fmt.Println(img.URL)
    }
}

Key Concepts

核心概念

IMG2 Grayscale Hit

IMG2灰度图命中

IMG2 is a grayscale (A/B test) feature on
chatgpt.com
that returns multiple high-res final images in a single call. The gateway:
  1. Sends the generation request
  2. Detects
    preview_only
    in the tool message response
  3. Automatically retries up to 3 times within the same conversation to capture IMG2 output
  4. Returns all signed image URLs aggregated
Use model
picture_v2
to specifically target the IMG2 grayscale path:
json
{ "model": "picture_v2", "prompt": "...", "n": 1 }
Successful IMG2 hit shows in logs:
image runner result summary turns_used=1 is_preview=false signed_count=2
IMG2是
chatgpt.com
上的灰度图(A/B测试)功能,单次调用可返回多张高清最终图片。网关的处理流程:
  1. 发送生成请求
  2. 检测工具消息响应中的
    preview_only
    标记
  3. 在同一会话中自动重试最多3次以捕获IMG2输出
  4. 返回所有聚合后的签名图片URL
使用
picture_v2
模型可专门针对IMG2灰度图路径:
json
{ "model": "picture_v2", "prompt": "...", "n": 1 }
成功命中IMG2会在日志中显示:
image runner result summary turns_used=1 is_preview=false signed_count=2

Account Pool Scheduling

账号池调度

The scheduler uses Redis distributed locks to serialize account usage:
  • min_interval_sec
    : minimum gap between consecutive uses of the same account
  • daily_usage_ratio
    : if an account hits this fraction of its daily limit, it's circuit-broken
  • cooldown_429_sec
    : account is cooled down after receiving a 429 from upstream
  • Accounts are bound 1:1 to
    oai-device-id
    /
    oai-session-id
    fingerprints (stored in DB)
调度器使用Redis分布式锁来序列化账号使用:
  • min_interval_sec
    : 同一账号连续使用的最小间隔秒数
  • daily_usage_ratio
    : 账号使用量达到每日限额的该比例后触发熔断
  • cooldown_429_sec
    : 账号收到上游429错误后的冷却时间
  • 账号与
    oai-device-id
    /
    oai-session-id
    指纹一对一绑定(存储在数据库中)

Image Proxy & Anti-Hotlink

图片代理与防盗链

All returned image URLs go through the built-in HMAC-signed proxy:
/p/img/:task_id/:index?exp=<unix_timestamp>&sig=<hmac_sha256>
This bypasses
chatgpt.com
's
estuary/content
403 hotlink protection. The proxy fetches and streams the image server-side when accessed.
所有返回的图片URL都经过内置的HMAC签名代理:
/p/img/:task_id/:index?exp=<unix_timestamp>&sig=<hmac_sha256>
这绕过了
chatgpt.com
estuary/content
403防盗链限制。代理会在访问时从服务器端获取并流式传输图片。

Credit Billing System

信用计费系统

  • Users have a credit wallet; credits are pre-deducted before generation
  • Group multipliers allow VIP / internal / reseller pricing tiers
  • Billing settled after successful generation; failed calls are refunded
  • EPay (易支付) integration for recharge

  • 用户拥有信用钱包;生成前预扣除信用
  • 分组倍率支持VIP/内部/经销商等不同定价层级
  • 生成成功后结算账单;调用失败则退款
  • 集成易支付(EPay)用于充值

Admin Operations

管理员操作

Account Pool Management

账号池管理

bash
undefined
bash
undefined

Check account statuses via API

通过API检查账号状态

curl http://localhost:8080/api/admin/accounts
-H "Authorization: Bearer $ADMIN_JWT"
curl http://localhost:8080/api/admin/accounts
-H "Authorization: Bearer $ADMIN_JWT"

Manually trigger account token refresh

手动触发账号令牌刷新

curl -X POST http://localhost:8080/api/admin/accounts/123/refresh
-H "Authorization: Bearer $ADMIN_JWT"
curl -X POST http://localhost:8080/api/admin/accounts/123/refresh
-H "Authorization: Bearer $ADMIN_JWT"

Bulk import accounts (JSON body)

批量导入账号(JSON请求体)

curl -X POST http://localhost:8080/api/admin/accounts/batch
-H "Authorization: Bearer $ADMIN_JWT"
-H "Content-Type: application/json"
-d @accounts.json
undefined
curl -X POST http://localhost:8080/api/admin/accounts/batch
-H "Authorization: Bearer $ADMIN_JWT"
-H "Content-Type: application/json"
-d @accounts.json
undefined

Database Backup & Restore

数据库备份与恢复

Via admin dashboard → Data Backup, or:
bash
undefined
通过管理控制台 → 数据备份,或使用命令:
bash
undefined

Trigger backup

触发备份

curl -X POST http://localhost:8080/api/admin/backups
-H "Authorization: Bearer $ADMIN_JWT"
curl -X POST http://localhost:8080/api/admin/backups
-H "Authorization: Bearer $ADMIN_JWT"

List backups

列出备份

curl http://localhost:8080/api/admin/backups
-H "Authorization: Bearer $ADMIN_JWT"
curl http://localhost:8080/api/admin/backups
-H "Authorization: Bearer $ADMIN_JWT"

Download backup

下载备份

curl http://localhost:8080/api/admin/backups/backup-2026-04-21.sql.gz
-H "Authorization: Bearer $ADMIN_JWT"
-o backup.sql.gz
undefined
curl http://localhost:8080/api/admin/backups/backup-2026-04-21.sql.gz
-H "Authorization: Bearer $ADMIN_JWT"
-o backup.sql.gz
undefined

User Credit Management

用户信用管理

bash
undefined
bash
undefined

Add credits to a user

为用户添加信用

curl -X POST http://localhost:8080/api/admin/users/42/credits
-H "Authorization: Bearer $ADMIN_JWT"
-H "Content-Type: application/json"
-d '{"amount": 10000, "note": "Manual top-up"}'

---
curl -X POST http://localhost:8080/api/admin/users/42/credits
-H "Authorization: Bearer $ADMIN_JWT"
-H "Content-Type: application/json"
-d '{"amount": 10000, "note": "Manual top-up"}'

---

Directory Structure

目录结构

gpt2api/
├── cmd/server/          # main entry point
├── configs/
│   ├── config.yaml      # main config
│   └── config.example.yaml
├── deploy/
│   ├── docker-compose.yml
│   ├── .env.example
│   └── README.md        # horizontal scaling guide
├── internal/
│   ├── api/             # Gin route handlers
│   ├── chatgpt/         # upstream client (utls, sentinel, SSE parser)
│   ├── scheduler/       # account pool scheduler + Redis leases
│   ├── billing/         # credit wallet + EPay integration
│   ├── proxy/           # proxy pool health checks
│   ├── imgproxy/        # HMAC-signed image proxy
│   └── model/           # DB models + migrations (goose)
├── web/                 # Vue 3 frontend source
└── docs/screenshots/

gpt2api/
├── cmd/server/          # 主入口
├── configs/
│   ├── config.yaml      # 主配置文件
│   └── config.example.yaml
├── deploy/
│   ├── docker-compose.yml
│   ├── .env.example
│   └── README.md        # 水平扩展指南
├── internal/
│   ├── api/             # Gin路由处理器
│   ├── chatgpt/         # 上游客户端(utls、sentinel、SSE解析器)
│   ├── scheduler/       # 账号池调度器 + Redis租赁
│   ├── billing/         # 信用钱包 + EPay集成
│   ├── proxy/           # 代理池健康检查
│   ├── imgproxy/        # HMAC签名图片代理
│   └── model/           # 数据库模型 + 迁移(goose)
├── web/                 # Vue 3前端源码
└── docs/screenshots/

Enabling Chat Completions

启用聊天补全

The
/v1/chat/completions
route is fully implemented but the UI entry is disabled via a feature flag due to upstream sentinel instability. To re-enable:
go
// internal/api/routes.go — find the feature flag:
const enableChatCompletions = false   // change to true
Rebuild and redeploy:
bash
docker compose up -d --build server

/v1/chat/completions
路由已完全实现,但由于上游sentinel不稳定,通过功能标志禁用了UI入口。如需重新启用:
go
// internal/api/routes.go — 找到功能标志:
const enableChatCompletions = false   // 修改为true
重新构建并部署:
bash
docker compose up -d --build server

Troubleshooting

故障排查

No accounts available / all accounts idle

无可用账号 / 所有账号闲置

bash
undefined
bash
undefined

Check account pool status

检查账号池状态

docker compose logs server | grep "scheduler"
docker compose logs server | grep "scheduler"

Common causes:

常见原因:

1. min_interval_sec too high — reduce in config

1. min_interval_sec设置过高 — 在配置中降低

2. All accounts in cooldown — check for 429s upstream

2. 所有账号处于冷却状态 — 检查上游是否返回429错误

3. Proxy unhealthy — verify proxy health score in dashboard

3. 代理不健康 — 在控制台中查看代理健康评分

undefined
undefined

Images return 403 when accessed directly

直接访问图片返回403

Expected behavior — all image URLs must go through the
/p/img/
proxy. Ensure
base_url
in config matches your actual domain so signed URLs are correct.
预期行为 — 所有图片URL必须通过
/p/img/
代理访问。确保配置中的
base_url
与实际域名一致,以便生成正确的签名URL。

is_preview=true
in logs (IMG2 not hitting)

日志中显示
is_preview=true
(未命中IMG2)

The account doesn't have IMG2 grayscale enabled. Either:
  • Try different accounts (grayscale is account-specific)
  • Use
    gpt-image-2
    model instead of
    picture_v2
  • The gateway retries up to 3 times automatically
该账号未启用IMG2灰度图功能。可尝试:
  • 使用其他账号(灰度图功能是账号专属的)
  • 使用
    gpt-image-2
    模型而非
    picture_v2
  • 网关会自动重试最多3次

Redis lock timeout errors

Redis锁超时错误

yaml
redis:
  pool_size: 500    # increase if seeing lock contention under high concurrency
yaml
redis:
  pool_size: 500    # 高并发下出现锁竞争时可增大该值

Database migration fails on startup

启动时数据库迁移失败

bash
docker compose exec server goose -dir /app/migrations mysql "$DSN" status
docker compose exec server goose -dir /app/migrations mysql "$DSN" up
bash
docker compose exec server goose -dir /app/migrations mysql "$DSN" status
docker compose exec server goose -dir /app/migrations mysql "$DSN" up

TLS fingerprint / JA3 detection

TLS指纹 / JA3检测

The gateway uses
refraction-networking/utls
to mimic Edge 143 browser TLS fingerprint. If accounts are getting flagged:
  • Ensure each account is bound to a dedicated proxy (avoid IP mixing)
  • Check
    oai-device-id
    binding is consistent (stored per-account in DB)
  • Rotate accounts that have been flagged
网关使用
refraction-networking/utls
模拟Edge 143浏览器的TLS指纹。如果账号被标记:
  • 确保每个账号绑定专属代理(避免IP混用)
  • 检查
    oai-device-id
    绑定是否一致(存储在数据库的账号记录中)
  • 更换已被标记的账号

High memory usage

内存占用过高

Reduce connection pool sizes for smaller deployments:
yaml
mysql:
  max_open_conns: 50
redis:
  pool_size: 50

对于小型部署,可减小连接池大小:
yaml
mysql:
  max_open_conns: 50
redis:
  pool_size: 50

Security Checklist

安全检查清单

  • Change default admin password immediately after first login
  • Set strong
    JWT_SECRET
    (≥32 chars random)
  • Set
    CRYPTO_AES_KEY
    to exactly 64 hex chars
  • Set strong MySQL passwords
  • Configure
    base_url
    to your HTTPS domain
  • Set up nginx reverse proxy with TLS in front of
    :8080
  • Configure API key IP whitelists for sensitive keys
  • Enable audit log review in admin dashboard
  • 首次登录后立即修改默认管理员密码
  • 设置强
    JWT_SECRET
    (≥32位随机字符)
  • 设置
    CRYPTO_AES_KEY
    为恰好64位十六进制字符
  • 设置强MySQL密码
  • base_url
    配置为HTTPS域名
  • :8080
    前端配置带TLS的nginx反向代理
  • 为敏感API密钥配置IP白名单
  • 在管理控制台中启用审计日志查看