534 lines
13 KiB
Markdown
534 lines
13 KiB
Markdown
# Sub2API
|
||
|
||
<div align="center">
|
||
|
||
[](https://golang.org/)
|
||
[](https://vuejs.org/)
|
||
[](https://www.postgresql.org/)
|
||
[](https://redis.io/)
|
||
[](https://www.docker.com/)
|
||
|
||
**AI API 网关平台 - 订阅配额分发管理**
|
||
|
||
[English](README.md) | 中文
|
||
|
||
</div>
|
||
|
||
---
|
||
|
||
## 在线体验
|
||
|
||
体验地址:**https://v2.pincc.ai/**
|
||
|
||
演示账号(共享演示环境;自建部署不会自动创建该账号):
|
||
|
||
| 邮箱 | 密码 |
|
||
|------|------|
|
||
| admin@sub2api.com | admin123 |
|
||
|
||
## 项目概述
|
||
|
||
Sub2API 是一个 AI API 网关平台,用于分发和管理 AI 产品订阅(如 Claude Code $200/月)的 API 配额。用户通过平台生成的 API Key 调用上游 AI 服务,平台负责鉴权、计费、负载均衡和请求转发。
|
||
|
||
## 核心功能
|
||
|
||
- **多账号管理** - 支持多种上游账号类型(OAuth、API Key)
|
||
- **API Key 分发** - 为用户生成和管理 API Key
|
||
- **精确计费** - Token 级别的用量追踪和成本计算
|
||
- **智能调度** - 智能账号选择,支持粘性会话
|
||
- **并发控制** - 用户级和账号级并发限制
|
||
- **速率限制** - 可配置的请求和 Token 速率限制
|
||
- **管理后台** - Web 界面进行监控和管理
|
||
|
||
## 技术栈
|
||
|
||
| 组件 | 技术 |
|
||
|------|------|
|
||
| 后端 | Go 1.25.7, Gin, Ent |
|
||
| 前端 | Vue 3.4+, Vite 5+, TailwindCSS |
|
||
| 数据库 | PostgreSQL 15+ |
|
||
| 缓存/队列 | Redis 7+ |
|
||
|
||
---
|
||
|
||
## 文档
|
||
|
||
- 依赖安全:`docs/dependency-security.md`
|
||
|
||
---
|
||
|
||
## OpenAI Responses 兼容注意事项
|
||
|
||
- 当请求包含 `function_call_output` 时,需要携带 `previous_response_id`,或在 `input` 中包含带 `call_id` 的 `tool_call`/`function_call`,或带非空 `id` 且与 `function_call_output.call_id` 匹配的 `item_reference`。
|
||
- 若依赖上游历史记录,网关会强制 `store=true` 并需要复用 `previous_response_id`,以避免出现 “No tool call found for function call output” 错误。
|
||
|
||
---
|
||
|
||
## 部署方式
|
||
|
||
### 方式一:脚本安装(推荐)
|
||
|
||
一键安装脚本,自动从 GitHub Releases 下载预编译的二进制文件。
|
||
|
||
#### 前置条件
|
||
|
||
- Linux 服务器(amd64 或 arm64)
|
||
- PostgreSQL 15+(已安装并运行)
|
||
- Redis 7+(已安装并运行)
|
||
- Root 权限
|
||
|
||
#### 安装步骤
|
||
|
||
```bash
|
||
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash
|
||
```
|
||
|
||
脚本会自动:
|
||
1. 检测系统架构
|
||
2. 下载最新版本
|
||
3. 安装二进制文件到 `/opt/sub2api`
|
||
4. 创建 systemd 服务
|
||
5. 配置系统用户和权限
|
||
|
||
#### 安装后配置
|
||
|
||
```bash
|
||
# 1. 启动服务
|
||
sudo systemctl start sub2api
|
||
|
||
# 2. 设置开机自启
|
||
sudo systemctl enable sub2api
|
||
|
||
# 3. 在浏览器中打开设置向导
|
||
# http://你的服务器IP:8080
|
||
```
|
||
|
||
设置向导将引导你完成:
|
||
- 数据库配置
|
||
- Redis 配置
|
||
- 管理员账号创建
|
||
|
||
#### 升级
|
||
|
||
可以直接在 **管理后台** 左上角点击 **检测更新** 按钮进行在线升级。
|
||
|
||
网页升级功能支持:
|
||
- 自动检测新版本
|
||
- 一键下载并应用更新
|
||
- 支持回滚
|
||
|
||
#### 常用命令
|
||
|
||
```bash
|
||
# 查看状态
|
||
sudo systemctl status sub2api
|
||
|
||
# 查看日志
|
||
sudo journalctl -u sub2api -f
|
||
|
||
# 重启服务
|
||
sudo systemctl restart sub2api
|
||
|
||
# 卸载
|
||
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/install.sh | sudo bash -s -- uninstall -y
|
||
```
|
||
|
||
---
|
||
|
||
### 方式二:Docker Compose(推荐)
|
||
|
||
使用 Docker Compose 部署,包含 PostgreSQL 和 Redis 容器。
|
||
|
||
#### 前置条件
|
||
|
||
- Docker 20.10+
|
||
- Docker Compose v2+
|
||
|
||
#### 快速开始(一键部署)
|
||
|
||
使用自动化部署脚本快速搭建:
|
||
|
||
```bash
|
||
# 创建部署目录
|
||
mkdir -p sub2api-deploy && cd sub2api-deploy
|
||
|
||
# 下载并运行部署准备脚本
|
||
curl -sSL https://raw.githubusercontent.com/Wei-Shaw/sub2api/main/deploy/docker-deploy.sh | bash
|
||
|
||
# 启动服务
|
||
docker-compose -f docker-compose.local.yml up -d
|
||
|
||
# 查看日志
|
||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||
```
|
||
|
||
**脚本功能:**
|
||
- 下载 `docker-compose.local.yml` 和 `.env.example`
|
||
- 自动生成安全凭证(JWT_SECRET、TOTP_ENCRYPTION_KEY、POSTGRES_PASSWORD)
|
||
- 创建 `.env` 文件并填充自动生成的密钥
|
||
- 创建数据目录(使用本地目录,便于备份和迁移)
|
||
- 显示生成的凭证供你记录
|
||
|
||
#### 手动部署
|
||
|
||
如果你希望手动配置:
|
||
|
||
```bash
|
||
# 1. 克隆仓库
|
||
git clone https://github.com/Wei-Shaw/sub2api.git
|
||
cd sub2api/deploy
|
||
|
||
# 2. 复制环境配置文件
|
||
cp .env.example .env
|
||
|
||
# 3. 编辑配置(生成安全密码)
|
||
nano .env
|
||
```
|
||
|
||
**`.env` 必须配置项:**
|
||
|
||
```bash
|
||
# PostgreSQL 密码(必需)
|
||
POSTGRES_PASSWORD=your_secure_password_here
|
||
|
||
# JWT 密钥(推荐 - 重启后保持用户登录状态)
|
||
JWT_SECRET=your_jwt_secret_here
|
||
|
||
# TOTP 加密密钥(推荐 - 重启后保留双因素认证)
|
||
TOTP_ENCRYPTION_KEY=your_totp_key_here
|
||
|
||
# 可选:管理员账号
|
||
ADMIN_EMAIL=admin@example.com
|
||
ADMIN_PASSWORD=your_admin_password
|
||
|
||
# 可选:自定义端口
|
||
SERVER_PORT=8080
|
||
```
|
||
|
||
**生成安全密钥:**
|
||
```bash
|
||
# 生成 JWT_SECRET
|
||
openssl rand -hex 32
|
||
|
||
# 生成 TOTP_ENCRYPTION_KEY
|
||
openssl rand -hex 32
|
||
|
||
# 生成 POSTGRES_PASSWORD
|
||
openssl rand -hex 32
|
||
```
|
||
|
||
```bash
|
||
# 4. 创建数据目录(本地版)
|
||
mkdir -p data postgres_data redis_data
|
||
|
||
# 5. 启动所有服务
|
||
# 选项 A:本地目录版(推荐 - 易于迁移)
|
||
docker-compose -f docker-compose.local.yml up -d
|
||
|
||
# 选项 B:命名卷版(简单设置)
|
||
docker-compose up -d
|
||
|
||
# 6. 查看状态
|
||
docker-compose -f docker-compose.local.yml ps
|
||
|
||
# 7. 查看日志
|
||
docker-compose -f docker-compose.local.yml logs -f sub2api
|
||
```
|
||
|
||
#### 部署版本对比
|
||
|
||
| 版本 | 数据存储 | 迁移便利性 | 适用场景 |
|
||
|------|---------|-----------|---------|
|
||
| **docker-compose.local.yml** | 本地目录 | ✅ 简单(打包整个目录) | 生产环境、频繁备份 |
|
||
| **docker-compose.yml** | 命名卷 | ⚠️ 需要 docker 命令 | 简单设置 |
|
||
|
||
**推荐:** 使用 `docker-compose.local.yml`(脚本部署)以便更轻松地管理数据。
|
||
|
||
#### 访问
|
||
|
||
在浏览器中打开 `http://你的服务器IP:8080`
|
||
|
||
如果管理员密码是自动生成的,在日志中查找:
|
||
```bash
|
||
docker-compose -f docker-compose.local.yml logs sub2api | grep "admin password"
|
||
```
|
||
|
||
#### 升级
|
||
|
||
```bash
|
||
# 拉取最新镜像并重建容器
|
||
docker-compose -f docker-compose.local.yml pull
|
||
docker-compose -f docker-compose.local.yml up -d
|
||
```
|
||
|
||
#### 轻松迁移(本地目录版)
|
||
|
||
使用 `docker-compose.local.yml` 时,可以轻松迁移到新服务器:
|
||
|
||
```bash
|
||
# 源服务器
|
||
docker-compose -f docker-compose.local.yml down
|
||
cd ..
|
||
tar czf sub2api-complete.tar.gz sub2api-deploy/
|
||
|
||
# 传输到新服务器
|
||
scp sub2api-complete.tar.gz user@new-server:/path/
|
||
|
||
# 新服务器
|
||
tar xzf sub2api-complete.tar.gz
|
||
cd sub2api-deploy/
|
||
docker-compose -f docker-compose.local.yml up -d
|
||
```
|
||
|
||
#### 常用命令
|
||
|
||
```bash
|
||
# 停止所有服务
|
||
docker-compose -f docker-compose.local.yml down
|
||
|
||
# 重启
|
||
docker-compose -f docker-compose.local.yml restart
|
||
|
||
# 查看所有日志
|
||
docker-compose -f docker-compose.local.yml logs -f
|
||
|
||
# 删除所有数据(谨慎!)
|
||
docker-compose -f docker-compose.local.yml down
|
||
rm -rf data/ postgres_data/ redis_data/
|
||
```
|
||
|
||
---
|
||
|
||
### 方式三:源码编译
|
||
|
||
从源码编译安装,适合开发或定制需求。
|
||
|
||
#### 前置条件
|
||
|
||
- Go 1.21+
|
||
- Node.js 18+
|
||
- PostgreSQL 15+
|
||
- Redis 7+
|
||
|
||
#### 编译步骤
|
||
|
||
```bash
|
||
# 1. 克隆仓库
|
||
git clone https://github.com/Wei-Shaw/sub2api.git
|
||
cd sub2api
|
||
|
||
# 2. 安装 pnpm(如果还没有安装)
|
||
npm install -g pnpm
|
||
|
||
# 3. 编译前端
|
||
cd frontend
|
||
pnpm install
|
||
pnpm run build
|
||
# 构建产物输出到 ../backend/internal/web/dist/
|
||
|
||
# 4. 编译后端(嵌入前端)
|
||
cd ../backend
|
||
go build -tags embed -o sub2api ./cmd/server
|
||
|
||
# 5. 创建配置文件
|
||
cp ../deploy/config.example.yaml ./config.yaml
|
||
|
||
# 6. 编辑配置
|
||
nano config.yaml
|
||
```
|
||
|
||
> **注意:** `-tags embed` 参数会将前端嵌入到二进制文件中。不使用此参数编译的程序将不包含前端界面。
|
||
|
||
**`config.yaml` 关键配置:**
|
||
|
||
```yaml
|
||
server:
|
||
host: "0.0.0.0"
|
||
port: 8080
|
||
mode: "release"
|
||
|
||
database:
|
||
host: "localhost"
|
||
port: 5432
|
||
user: "postgres"
|
||
password: "your_password"
|
||
dbname: "sub2api"
|
||
|
||
redis:
|
||
host: "localhost"
|
||
port: 6379
|
||
password: ""
|
||
|
||
jwt:
|
||
secret: "change-this-to-a-secure-random-string"
|
||
expire_hour: 24
|
||
|
||
default:
|
||
user_concurrency: 5
|
||
user_balance: 0
|
||
api_key_prefix: "sk-"
|
||
rate_multiplier: 1.0
|
||
```
|
||
|
||
`config.yaml` 还支持以下安全相关配置:
|
||
|
||
- `cors.allowed_origins` 配置 CORS 白名单
|
||
- `security.url_allowlist` 配置上游/价格数据/CRS 主机白名单
|
||
- `security.url_allowlist.enabled` 可关闭 URL 校验(慎用)
|
||
- `security.url_allowlist.allow_insecure_http` 关闭校验时允许 HTTP URL
|
||
- `security.url_allowlist.allow_private_hosts` 允许私有/本地 IP 地址
|
||
- `security.response_headers.enabled` 可启用可配置响应头过滤(关闭时使用默认白名单)
|
||
- `security.csp` 配置 Content-Security-Policy
|
||
- `billing.circuit_breaker` 计费异常时 fail-closed
|
||
- `server.trusted_proxies` 启用可信代理解析 X-Forwarded-For
|
||
- `turnstile.required` 在 release 模式强制启用 Turnstile
|
||
|
||
**⚠️ 安全警告:HTTP URL 配置**
|
||
|
||
当 `security.url_allowlist.enabled=false` 时,系统默认执行最小 URL 校验,**拒绝 HTTP URL**,仅允许 HTTPS。要允许 HTTP URL(例如用于开发或内网测试),必须显式设置:
|
||
|
||
```yaml
|
||
security:
|
||
url_allowlist:
|
||
enabled: false # 禁用白名单检查
|
||
allow_insecure_http: true # 允许 HTTP URL(⚠️ 不安全)
|
||
```
|
||
|
||
**或通过环境变量:**
|
||
|
||
```bash
|
||
SECURITY_URL_ALLOWLIST_ENABLED=false
|
||
SECURITY_URL_ALLOWLIST_ALLOW_INSECURE_HTTP=true
|
||
```
|
||
|
||
**允许 HTTP 的风险:**
|
||
- API 密钥和数据以**明文传输**(可被截获)
|
||
- 易受**中间人攻击 (MITM)**
|
||
- **不适合生产环境**
|
||
|
||
**适用场景:**
|
||
- ✅ 开发/测试环境的本地服务器(http://localhost)
|
||
- ✅ 内网可信端点
|
||
- ✅ 获取 HTTPS 前测试账号连通性
|
||
- ❌ 生产环境(仅使用 HTTPS)
|
||
|
||
**未设置此项时的错误示例:**
|
||
```
|
||
Invalid base URL: invalid url scheme: http
|
||
```
|
||
|
||
如关闭 URL 校验或响应头过滤,请加强网络层防护:
|
||
- 出站访问白名单限制上游域名/IP
|
||
- 阻断私网/回环/链路本地地址
|
||
- 强制仅允许 TLS 出站
|
||
- 在反向代理层移除敏感响应头
|
||
|
||
```bash
|
||
# 6. 运行应用
|
||
./sub2api
|
||
```
|
||
|
||
#### 开发模式
|
||
|
||
```bash
|
||
# 后端(支持热重载)
|
||
cd backend
|
||
go run ./cmd/server
|
||
|
||
# 前端(支持热重载)
|
||
cd frontend
|
||
pnpm run dev
|
||
```
|
||
|
||
#### 代码生成
|
||
|
||
修改 `backend/ent/schema` 后,需要重新生成 Ent + Wire:
|
||
|
||
```bash
|
||
cd backend
|
||
go generate ./ent
|
||
go generate ./cmd/server
|
||
```
|
||
|
||
---
|
||
|
||
## 简易模式
|
||
|
||
简易模式适合个人开发者或内部团队快速使用,不依赖完整 SaaS 功能。
|
||
|
||
- 启用方式:设置环境变量 `RUN_MODE=simple`
|
||
- 功能差异:隐藏 SaaS 相关功能,跳过计费流程
|
||
- 安全注意事项:生产环境需同时设置 `SIMPLE_MODE_CONFIRM=true` 才允许启动
|
||
|
||
---
|
||
|
||
## Antigravity 使用说明
|
||
|
||
Sub2API 支持 [Antigravity](https://antigravity.so/) 账户,授权后可通过专用端点访问 Claude 和 Gemini 模型。
|
||
|
||
### 专用端点
|
||
|
||
| 端点 | 模型 |
|
||
|------|------|
|
||
| `/antigravity/v1/messages` | Claude 模型 |
|
||
| `/antigravity/v1beta/` | Gemini 模型 |
|
||
|
||
### Claude Code 配置示例
|
||
|
||
```bash
|
||
export ANTHROPIC_BASE_URL="http://localhost:8080/antigravity"
|
||
export ANTHROPIC_AUTH_TOKEN="sk-xxx"
|
||
```
|
||
|
||
### 混合调度模式
|
||
|
||
Antigravity 账户支持可选的**混合调度**功能。开启后,通用端点 `/v1/messages` 和 `/v1beta/` 也会调度该账户。
|
||
|
||
> **⚠️ 注意**:Anthropic Claude 和 Antigravity Claude **不能在同一上下文中混合使用**,请通过分组功能做好隔离。
|
||
|
||
|
||
### 已知问题
|
||
在 Claude Code 中,无法自动退出Plan Mode。(正常使用原生Claude Api时,Plan 完成后,Claude Code会弹出弹出选项让用户同意或拒绝Plan。)
|
||
解决办法:shift + Tab,手动退出Plan mode,然后输入内容 告诉 Claude Code 同意或拒绝 Plan
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
sub2api/
|
||
├── backend/ # Go 后端服务
|
||
│ ├── cmd/server/ # 应用入口
|
||
│ ├── internal/ # 内部模块
|
||
│ │ ├── config/ # 配置管理
|
||
│ │ ├── model/ # 数据模型
|
||
│ │ ├── service/ # 业务逻辑
|
||
│ │ ├── handler/ # HTTP 处理器
|
||
│ │ └── gateway/ # API 网关核心
|
||
│ └── resources/ # 静态资源
|
||
│
|
||
├── frontend/ # Vue 3 前端
|
||
│ └── src/
|
||
│ ├── api/ # API 调用
|
||
│ ├── stores/ # 状态管理
|
||
│ ├── views/ # 页面组件
|
||
│ └── components/ # 通用组件
|
||
│
|
||
└── deploy/ # 部署文件
|
||
├── docker-compose.yml # Docker Compose 配置
|
||
├── .env.example # Docker Compose 环境变量
|
||
├── config.example.yaml # 二进制部署完整配置文件
|
||
└── install.sh # 一键安装脚本
|
||
```
|
||
|
||
## 许可证
|
||
|
||
MIT License
|
||
|
||
---
|
||
|
||
<div align="center">
|
||
|
||
**如果觉得有用,请给个 Star 支持一下!**
|
||
|
||
</div>
|