prism2api 部署到 VPS:把 Prism 网页会话变成 OpenAI 兼容 API

prism2api 把 prism.openai.com 的网页会话重放成本地 OpenAI 兼容端点。本文给出 VPS 上的完整部署流程——环境、凭据导入、分级验证、systemd 守护、SSH 隧道与安全加固、错误码排查;并诚实说明一个决定成败的事实:Cookie 里的 Cloudflare 令牌绑定来源 IP,跨网络搬到机房大概率直接 403。

本文整理自 GitHub 项目 Robinfxa/prism2api(v1.0.0 Direct HTTP release,MIT 许可)的 README、使用手册与源码,命令与限制忠于原文,章节组织、安全加固与评述为本文编辑归纳。所有步骤均对照仓库 CLI 与源码核对。

先说清楚它是什么:把你浏览器里已登录好的 prism.openai.com 会话复制出来,在服务器上重放,包装成一个 OpenAI 格式的本地 HTTP 接口。

它不是什么:不是官方 API,不做自动登录与凭据刷新,不支持流式(SSE)、tools、多轮消息、多模态、模型选择,不返回 token 用量,model 永远是本地别名 prism-default(项目明确声明这不是已证实的上游模型身份)。

⚠️ 合规提示:这是逆向工程项目,需要你上传本人登录会话 Cookie 并绕过网页前端直接调内部接口,极可能违反 OpenAI / Prism 服务条款,存在限流或封号风险。本文仅作技术记录,不构成使用建议。若你只是想要能调 GPT 类模型的 API,直接用官方 API——自建这套的运维成本远高于那点费用。


一、⚠️ 先读完这节,否则会白忙两小时

有个问题普通教程不会写,但它直接决定这件事在 VPS 上成不成。

从 DevTools 复制的请求头里,Cookie 包含这四个关键项:

Cookie说明
prism_session_tokenPrism 会话 JWT
prism_oai_access_tokenauth.openai.com 签发的 OAuth token
__cf_bmCloudflare Bot Management 令牌
cf_clearanceCloudflare 挑战通过凭证

后两个是 Cloudflare 用来标识"这是通过人机验证的真实浏览器"的令牌,通常与来源 IP、User-Agent、TLS 指纹绑定。

结论很直接:

你在家里浏览器抓到的 Cookie,搬到 VPS 的机房 IP 上去用,大概率直接 403。

表现为心跳失败,或提交时返回 upstream_forbidden / upstream_unauthorized。此外项目还要求一个 x-crixet-sandbox-token 用于 heartbeat(/s/sandboxes/proxy/heartbeat),这个沙箱是网页端拉起的运行时,能否从异地 IP 维持心跳,项目方自己也没验证过。

1.2 作者自己承认:真实请求从未跑过

项目 docs/validation/direct-http-0.2.0rc1.md 原文:

Live Prism: NOT_RUN; fresh local credential capture still required.

那些"91 passed / 103 passed"全是离线合同测试 + mock 测试 + 本机回环测试。主 transport PrismWebTransport 的 submit_task 直接 raise RuntimeError,整个模块标注为 unverified scaffold。

1.3 可行性速查

场景可行性
在抓包那台机器本机上跑相对最可行,仍需自行验证
抓包后几分钟内、同网络出口有可能
跨网络搬到 VPS 长期跑很低,且不保证稳定
做生产级 API不可能

下面每一步都标了验证点,让你尽早知道成不成,而不是装完两小时才发现白搭。


二、环境准备

项目要求
系统Linux。源码硬编码 os.name != 'posix' 直接抛 platform_unsupported,Windows 不支持运行目录锁
Python≥ 3.12(pyproject.toml 写 >=3.11,但 standalone wheel 要 3.12+,建议直接上 3.12)
内存512 MB 足够
网络能直连 prism.openai.com

推荐 Ubuntu 24.04 LTS(自带 Python 3.12)。若是 22.04(自带 3.10),需加 deadsnakes:

sudo apt update && sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:deadsnakes/ppa
sudo apt install -y python3.12 python3.12-venv python3.12-dev

安装其余依赖:

sudo apt install -y git python3-pip ufw

创建专用低权限用户

别用 root 跑——这程序持有你的账号凭据。

sudo useradd -r -m -s /bin/bash prism
sudo passwd -l prism          # 锁密码,防止直接登录

三、安装

sudo -iu prism
cd ~
git clone https://github.com/Robinfxa/prism2api.git
cd prism2api

供应链提示:该仓库创建仅数天、单作者、无 release、无 CI。建议锁定到具体 commit 而不是跟 main:

git log --oneline -5        # 先审一遍历史
git checkout <你审阅过的 SHA>

建虚拟环境并安装:

python3.12 -m venv .venv
.venv/bin/python -m pip install --upgrade pip
.venv/bin/python -m pip install -e '.[dev]'

依赖只有四个主流包:

pydantic>=2.10,<3
fastapi>=0.115,<1
httpx>=0.27,<1
uvicorn>=0.30,<1

走 Direct HTTP 路径不需要 [browser] 里的 playwright,那是已废弃的浏览器实验路径。

自检:

.venv/bin/python -m prism2api.direct --help
.venv/bin/python -m pytest -q

应看到子命令:import-curl / serve-http / probe-http / doctor-http / smoke-http / reconcile-http / run-status / acknowledge-run。


四、获取并导入凭据(最关键、也最危险)

4.1 本地浏览器操作

  1. 用本人账号登录 prism.openai.com
  2. 打开一个能正常工作的项目,先让它完整回答一条简单问题
  3. DevTools → Network,找到那条 response_with_tools_start
  4. 右键 → Copy as cURL (bash)

⚠️ 必须选 bash 格式。程序只解析 bash 的 $'...' 引号语法,zsh / cmd 会解析失败。

⚠️ 不要把这段内容贴进任何聊天窗口、GitHub issue 或命令行参数——它等价于账号密码。

4.2 传到 VPS

在本地机器上(不要经过网盘 / 聊天工具 / 任何中转):

cat > /tmp/prism.curl <<'EOF'
<粘贴你复制的 cURL>
EOF
chmod 600 /tmp/prism.curl
scp -p /tmp/prism.curl prism@<你的VPS IP>:/home/prism/prism.curl

到 VPS 上确认权限:

sudo -iu prism
chmod 600 ~/prism.curl
ls -l ~/prism.curl      # 必须是 -rw------- 且属主 prism

程序会强制校验:文件必须属当前用户、权限 0600,不符直接拒绝。别想着绕过,这是它的安全设计。

4.3 导入并立即销毁明文

cd ~/prism2api
.venv/bin/python -m prism2api.direct import-curl --file ~/prism.curl
shred -u ~/prism.curl

导入成功写出:

~/.prism2api/direct/bootstrap.json     # 0600

⚠️ 这个文件不只是 Cookie。 它保存完整 metadata、codex_listen_snapshot,以及原始请求的 system prompt 和历史上下文。也就是说它同时是凭据和你的私有项目内容。绝不上传、不备份到网盘、不提交进 git。

项目 .gitignore 已排除 bootstrap*.json、gateway.key、*.curl、*.har——别手贱改它。

4.4 导入失败的常见原因

程序要求这一次请求同时包含:Cookie、User-Agent、project_id / user_id / conversation_id、sandbox URL 与 token、codex_listen_snapshot。

缺任一项报 incomplete,程序不会用旧值补齐(设计原则:宁可拒绝,不猜字段)。解决方式是回网页重新发一条请求、重新 Copy as cURL。


五、分级验证(决定你要不要继续)

按顺序做,任何一步失败就停下来排查。

5.1 纯本地格式检查(不联网)

.venv/bin/python -m prism2api.direct doctor-http --offline

只验 bootstrap.json 格式完整性。通过只代表文件格式对,不代表能连通。

5.2 心跳(第一次真正联网)

.venv/bin/python -m prism2api.direct doctor-http
  • ✅ heartbeat: ok → 凭据至少还活着,继续
  • ❌ heartbeat_unavailable / upstream_forbidden → 大概率就是 §1.1 的 Cloudflare IP 绑定问题

即便心跳成功也不等于生成能成功。项目原文:“成功也不等于 generation 已验证”。

5.3 真实生成探针(唯一可信判据)

.venv/bin/python -m prism2api.direct probe-http \
  --prompt 'Reply exactly: PRISM_HTTP_CHECK' --timeout 180

判据非常明确:返回的 result.text 逐字等于 PRISM_HTTP_CHECK 才算成功。

  • ✅ 一致 → 你的环境确实能跑,继续部署
  • ❌ 其他任何结果 → 停,不要循环发十条重试,按 §8 排查

想再压一轮可以跑 smoke-http --count 3,它会在首个失败就停止,未执行的项标记 not_run,不会把单元测试或错误请求算成真实成功。


六、systemd 守护

确认 §5.3 真的通过后再配常驻。

sudo tee /etc/systemd/system/prism2api.service >/dev/null <<'EOF'
[Unit]
Description=prism2api direct-http gateway
After=network.target

[Service]
Type=simple
User=prism
Group=prism
WorkingDirectory=/home/prism/prism2api
Environment=HOME=/home/prism
ExecStart=/home/prism/prism2api/.venv/bin/python -m prism2api.direct serve-http --port 8765 --timeout 180
Restart=on-failure
RestartSec=5

# --- 安全加固 ---
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=false
ReadWritePaths=/home/prism/.prism2api
ProtectKernelTunables=true
ProtectControlGroups=true
RestrictSUIDSGID=true

[Install]
WantedBy=multi-user.target
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now prism2api
sudo systemctl status prism2api
journalctl -u prism2api -f

ProtectSystem=strict 把整个文件系统挂成只读,只通过 ReadWritePaths 放开 journal 数据库目录。代码目录运行时只读即可。

单进程锁

程序用 flock 保证同一 home 只允许一个进程。若看到:

runtime_busy: Another direct runtime or import is active in this home.

先停服务:

sudo systemctl stop prism2api
pgrep -af prism2api       # 确认无残留

每次重新 import-curl 前必须先停服务,否则导入会被锁拒绝。


七、安全加固(不做完不要对外开放)

7.1 服务只绑回环

程序默认只绑 127.0.0.1 或 ::1,且不提供 --host 0.0.0.0 这类选项。不要想办法突破它。

sudo ss -tlnp | grep 8765      # 应看到 127.0.0.1:8765,不是 0.0.0.0:8765

7.2 防火墙只开 SSH

sudo ufw default deny incoming
sudo ufw allow OpenSSH
sudo ufw enable

绝不要 ufw allow 8765。 这个接口一旦暴露公网,等于把你的 OpenAI 账号挂在网上任人调用。

7.3 用 SSH 隧道访问

在你自己电脑上:

ssh -N -L 8765:127.0.0.1:8765 prism@<你的VPS IP>

想长期用,写进 ~/.ssh/config:

Host prism-vps
    HostName <你的VPS IP>
    User prism
    LocalForward 8765 127.0.0.1:8765
    ServerAliveInterval 60

之后 ssh -N prism-vps 即可。

项目文档说"不可公网暴露或通过 tunnel 转发"——指的是 frp / ngrok 这类公网穿透。SSH 本地端口转发不在此列,是安全的。

7.4 本地调用密钥

服务启动生成 ~/.prism2api/direct/gateway.key(0600),除 /healthz 外所有接口都要带:

sudo -iu prism
cat ~/.prism2api/direct/gateway.key

八、调用示例

健康检查(无需鉴权)

curl http://127.0.0.1:8765/healthz

curl 调用

KEY=$(sudo -iu prism cat /home/prism/.prism2api/direct/gateway.key)

curl http://127.0.0.1:8765/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $KEY" \
  -H "Idempotency-Key: req-001" \
  -d '{
    "model": "prism-default",
    "messages": [{"role": "user", "content": "用中文解释强化学习。"}]
  }'

Python 调用

from pathlib import Path
import httpx

key = Path('/home/prism/.prism2api/direct/gateway.key').read_text().strip()

with httpx.Client(trust_env=False, timeout=190) as client:
    r = client.post(
        'http://127.0.0.1:8765/v1/chat/completions',
        headers={
            'Authorization': 'Bearer ' + key,
            'Idempotency-Key': 'my-request-001',
        },
        json={
            'model': 'prism-default',
            'messages': [{'role': 'user', 'content': '用中文解释强化学习。'}],
        },
    )
    r.raise_for_status()
    print(r.json()['choices'][0]['message']['content'])

接口清单与限制

接口说明
GET /healthz配置/忙闲状态,不含凭据
GET /v1/models只返回本地别名 prism-default,不是模型身份确认
POST /v1/chat/completions单条 user 文本、非流式、n=1
GET /v1/runs/{run_id}查本地任务状态与调用计数

会被明确拒绝(不静默丢弃):多条 messages、tools、system / developer role、stream: true、任何未支持的额外参数。

并发:固定项目/会话共享上游上下文,同一时刻只允许一条任务,忙时返回 409,不排队。


九、故障排查

9.1 错误码对照

错误码含义处理
upstream_unauthorized / sandbox_unauthorized上游或 sandbox 拒绝凭据过期/不匹配。回网页确认能正常回答,重新 Copy as cURL
sandbox_not_ready / sandbox_sync_timeout远端明确失败程序不会自动重试提交,需人工处理
uncertain可能已发出 start,结果不明该目录会阻止下一次生成,重启也不清除,见 9.2
busy (409)已有请求在进行等待或串行化调用
runtime_busy (409)同 home 已有进程systemctl stop 后重试

9.2 处理 uncertain(务必按规矩来)

sudo systemctl stop prism2api
cd ~/prism2api

# 只查询,不重新提交
.venv/bin/python -m prism2api.direct run-status --run run_...
.venv/bin/python -m prism2api.direct reconcile-http --run run_...

只有人工在网页上确认原任务已停止后,才可执行:

.venv/bin/python -m prism2api.direct acknowledge-run --run run_... --remote-stopped

这会留下 abandoned / operator_confirmed_remote_stopped 的人工记录。

❌ 严禁:为继续测试随手加 --remote-stopped;或删库、换 home 目录绕过闸门。程序这么设计就是防重复提交与资源泄漏。

9.3 凭据失效

Cookie 会过期,没有自动刷新机制。表现是突然全部 upstream_unauthorized。处理:停服务 → 重抓 → 重新 import-curl → 启服务。


十、卸载与善后

sudo systemctl stop prism2api
sudo systemctl disable prism2api
sudo rm /etc/systemd/system/prism2api.service
sudo systemctl daemon-reload

sudo -iu prism
rm -rf ~/prism2api ~/.prism2api

若凭据有任何泄漏嫌疑,立即:在 OpenAI / Prism 网页端登出所有会话 → 改密码 → 查账号活动记录。


十一、客观评价

跑完全流程,我的看法是:代码质量明显高于同类逆向项目,但它依然不是值得投入的东西。

值得肯定的工程细节

  • secure.py 用 O_NOFOLLOW 防符号链接劫持、flock 防双写、O_EXCL + fsync 原子写、强制 0600
  • 拒绝把私有状态放在 Git 目录内(runtime_in_repository)
  • 强制 follow_redirects=False,源码注释点明理由:防止导入的 URL 重定向导致 Cookie 外泄
  • 主动丢弃 hop-by-hop 头部(host / content-length / connection 等),避免请求走私
  • 未知结局进 uncertain 并阻断新生成,而不是偷偷重试
  • 全仓无 subprocess / eval / 遥测 / 外发通道;依赖只有 4 个主流包

但结构性问题是工程水平解决不了的

  1. 跨网络凭据基本不可移植(Cloudflare 令牌 IP 绑定)
  2. 真实链路从未验证(作者自承 NOT_RUN)
  3. 违反服务条款,封号风险自担
  4. 单人、数天历史、0 release、无 CI,随时可能烂尾或被强推恶意提交
  5. 需周期性手动重抓 Cookie,无法长期无人值守

建议

你的目的建议
想要能用的 GPT API用官方 API,别折腾
想学协议逆向 / 本地网关安全工程值得读源码(secure.py、bootstrap.py、engine.py),不必真跑
想省钱绕过额度别,封号代价更高
纯好奇想试试用一次性账号,隔离环境,用完即弃

项目状态截至 2026-10-01。若上游接口或仓库有更新,请以仓库 README 与 docs/guides/direct-http.md 为准。