| --- |
| title: Claude2API |
| emoji: 🔁 |
| colorFrom: purple |
| colorTo: indigo |
| sdk: docker |
| app_port: 7860 |
| pinned: false |
| --- |
| |
| # Claude2API — Hugging Face Space 说明 |
|
|
| 当前 Space:<https://ohmyapi-c2api.hf.space> |
|
|
| 这是一个围绕 `pushzx/claude2api:latest` 的 Hugging Face Docker Space 包装层。目标很克制: |
|
|
| - 让根路径 `/` 直接进入真实可用的管理登录页 `/admin/login` |
| - 保持 `/admin`、`/health`、`/v1/*` 等能力继续由上游 `claude2api` 提供 |
| - wrapper 只处理入口体验与反代,不在外层伪造持久化配置语义 |
|
|
| ## 当前部署状态 |
|
|
| 当前线上状态已经收敛为 **public Space + simple mode**。 |
|
|
| - Space 类型:**public Space** |
| - 运行模式:**simple mode** |
| - 当前不启用 DB-backed 持久化 |
| - 当前已从 Space Secrets 中移除:`DB_HOST`、`DB_PORT`、`DB_USER`、`DB_PASS`、`DB_NAME`、`PGSSLMODE` |
| - 当前根路径 `/` 会直接 `302` 到 `/admin/login` |
|
|
| 这样收敛的原因很明确:simple mode 已经稳定可用,而当前上游镜像的 DB-only 路径对 Neon / Supabase 这类强制 TLS 的托管 PostgreSQL 仍未验证通过,不能在这里把它写成现成功能。 |
|
|
| ## 当前访问行为 |
|
|
| public Space 的含义是:**入口默认公开**,不是 **Secrets 自动公开**。 |
|
|
| 当前线上已验证: |
|
|
| - `/` → `302 /admin/login` |
| - `/admin/login` 可正常打开 |
| - `/health` 返回 `200` |
| - `/v1/messages` 未带正确 token 时返回 `401 Invalid API key` |
| - 带正确 app token 时,`claude-sonnet-4-6` 已成功完成实际调用 |
| - `/v1/models` 可在带 token 的情况下返回模型列表 |
|
|
| ## public Space 的风险边界 |
|
|
| public Space 不会因为是 public 就把 Hugging Face Secrets 直接暴露出来,但它会让你的入口地址处于公网可探测状态。 |
|
|
| 这意味着: |
|
|
| - `https://ohmyapi-c2api.hf.space/` 这类地址任何人都能访问与探测 |
| - Hugging Face Space Secrets **不会**被页面或公开 API 直接回显 |
| - 真正更常见的泄露面是:把 token / session 写进仓库文件、前端页面、日志、导出的配置或本机历史文件 |
| - public Space 是否安全,关键不在于“是否 public”,而在于: |
| - app 自身接口是否强制鉴权 |
| - `CLAUDE_API_KEY` / `CLAUDE_SESSION_KEYS` 是否只保留在服务端运行时环境 |
| - 仓库与页面输出里是否完全不出现真实 secret |
|
|
| 换句话说,public Space **不会自动泄露 session**,但如果 app token 泄露、接口未加保护,别人就能直接消费你的服务。 |
|
|
| ## 为什么 Hugging Face 环境变量能直接生效 |
|
|
| 因为当前 Space 使用的是 **Docker SDK**。 |
|
|
| Hugging Face 对 Docker Space 的处理方式不是“把变量写进仓库文件”,而是在容器启动时把 Space Settings 里的: |
|
|
| - **Variables** |
| - **Secrets** |
|
|
| 直接注入成容器进程的真实运行时环境变量。 |
|
|
| 对这个仓库来说,等价于容器启动时直接拿到了例如: |
|
|
| ```env |
| ADMIN_USER=admin |
| LISTEN_ADDR=:7860 |
| CLAUDE_API_KEY=... |
| ADMIN_PASS=... |
| CLAUDE_SESSION_KEYS=... |
| ``` |
|
|
| 因此,只要上游 `claude2api` 在启动时通过 `os.Getenv(...)` 或等价方式读取配置,它就会直接生效,不需要额外写入 `.env`、`config.yaml` 或其它文件。 |
|
|
| ### 当前已确认的 Space Variables |
|
|
| 当前公开可读到的 Variables 是: |
|
|
| ```env |
| LISTEN_ADDR=:7860 |
| ADMIN_USER=admin |
| ``` |
|
|
| Secrets 不会被 Hugging Face API 直接回显,但从线上行为可以确认至少存在并已生效: |
|
|
| - `CLAUDE_API_KEY` |
| - `CLAUDE_SESSION_KEYS` |
| - `ADMIN_PASS` |
|
|
| ## 当前 wrapper 做了什么 |
|
|
| 当前 `Dockerfile` 不是直接把上游镜像原样暴露到 `:7860`,而是: |
|
|
| - 前置一个很薄的 nginx |
| - nginx 监听 `:7860` |
| - 上游 `claude2api` 在容器内监听 `127.0.0.1:8080` |
| - `/` 与 `/index.html` 直接跳转到 `/admin/login` |
| - 其余路径继续透传到上游 |
|
|
| 这样做的原因很简单: |
|
|
| - 旧版 root path 会显示 `404 page not found` |
| - 现在用户访问根路径时,会直接进入真实可用的登录入口 |
| - 同时不需要去改上游镜像源码 |
|
|
| ## 当前为什么不启用 PostgreSQL 持久化 |
|
|
| ### 结论 |
|
|
| **按当前已验证状态,不能认为这个 Space 已经配置并启用了 PostgreSQL 持久化存储。** |
|
|
| 更准确地说:当前线上已经明确收敛为 **simple mode only**,不是“正在尝试 DB-only 但尚未成功”。 |
|
|
| ### 原因 |
|
|
| 1. 只要存在 `CLAUDE_SESSION_KEYS`,上游就可以走 simple mode,并且当前已验证可稳定提供 API 能力。 |
| 2. 当前 Hugging Face Space runtime 已确认 `storage.current = None` 且 `storage.requested = None`,因此容器内本地 PostgreSQL 不能视为正式持久化层。 |
| 3. 对当前上游镜像的排查显示,DB-only 路径很可能会把 PostgreSQL DSN 拼成: |
|
|
| ```text |
| host=%s port=%s user=%s password=%s dbname=%s sslmode=disable |
| ``` |
|
|
| 这会与 Neon / Supabase 这类强制 TLS 的托管 PostgreSQL 冲突。 |
| 4. 因此,即使文档里存在“可连接外部数据库”的描述,也不能把它等同于“当前镜像已支持外部托管 PG 持久化”。 |
|
|
| ### 为什么 local PostgreSQL 不能当成 HF 持久化 |
|
|
| 如果你打算在 Hugging Face Space 容器里直接放一个“本地 PostgreSQL”,要先明确一件事:**默认情况下,这不等于可靠持久化。** |
|
|
| 原因是: |
|
|
| 1. Docker Space 默认使用的是容器自身的可写层,而不是天然持久卷。 |
| 2. 如果没有单独申请 Hugging Face persistent storage,并把数据库目录明确挂到持久路径,本地 PG 数据在 restart / rebuild / redeploy 后都可能丢失。 |
| 3. 当前这个 Space 没有启用 persistent storage,因此“容器内本地 PG”不能当成正式配置持久化方案。 |
|
|
| 因此: |
|
|
| - 本地 PG 更适合临时调试,不适合承担当前 Space 的正式配置持久化 |
| - 真正需要稳定持久化时,应优先使用外部 PostgreSQL,或者先补齐 HF persistent storage,再验证上游是否支持对应的数据目录语义 |
|
|
| ## 当前推荐的线上配置思路 |
|
|
| 如果你只是想把 Space 稳定跑起来,当前推荐就是保持 simple mode: |
|
|
| ### 必要 Secrets |
|
|
| - `CLAUDE_SESSION_KEYS` |
| - `CLAUDE_API_KEY` |
| - `ADMIN_PASS` |
|
|
| ### 当前 Variables |
|
|
| ```env |
| LISTEN_ADDR=:7860 |
| ADMIN_USER=admin |
| ``` |
|
|
| ### 当前不启用的配置 |
|
|
| 以下 DB 相关项当前视为**暂不启用**,不要再把它们当成线上必需配置: |
|
|
| - `DB_HOST` |
| - `DB_PORT` |
| - `DB_USER` |
| - `DB_PASS` |
| - `DB_NAME` |
| - `PGSSLMODE` |
|
|
| ## 当前已验证可调用的模型 |
|
|
| 带正确 app token 时,以下模型已通过真实 `/v1/messages` 请求验证,可以正常返回结果: |
|
|
| - `claude-sonnet-4-5` |
| - `claude-haiku-4-5` |
| - `claude-sonnet-4-6` |
| - `claude-haiku-4-6` |
| - `claude-3-5-sonnet-20241022` |
| - `claude-3-5-haiku-20241022` |
| - `claude-3-sonnet-20240229` |
| - `claude-3-haiku-20240307` |
|
|
| 以下模型虽然会出现在 `/v1/models` 列表里,但当前实测返回的是 `403 model_not_available`: |
|
|
| - `claude-opus-4-5` |
| - `claude-opus-4-6` |
| - `claude-3-opus-20240229` |
|
|
| 这也说明一件事:**`/v1/models` 返回的是“当前镜像声明支持的模型列表”,真正能否调用仍然取决于当前 session / account 的实际可用性。** |
|
|
| ## 关于 admin password / auth token 持久化的当前结论 |
|
|
| 目前已做过的验证结论是: |
|
|
| - `api_key` 可以在当前运行期通过管理接口更新,并立即影响鉴权结果 |
| - 但容器重启后,会回退到启动时环境变量 / HF Secrets 的值 |
| - `admin_pass` 目前看**不能**通过现有 settings 路径真正更新并持久生效 |
|
|
| 所以当前更准确的理解是: |
|
|
| - Hugging Face Secrets / Variables = **启动配置源** |
| - 上游 admin UI 的部分设置 = **运行期状态修改** |
| - 两者目前**不是**一个可自动回写、可稳定持久继承的统一配置层 |
|
|
| ## 当前仓库文件职责 |
|
|
| - `Dockerfile`:构建 HF Space 容器 |
| - `nginx.conf`:把根路径重定向到 `/admin/login`,并透传其他请求 |
| - `entrypoint.sh`:同时启动前置 nginx 和上游 `claude2api` |
| - `.env.example`:本地 / VPS 运行示例,不代表 HF Secrets 会被运行时回写 |
| - `docker-compose.yml`:本地 / VPS 参考,不会直接在 HF Space 中运行 |
|
|
| ## 最小验收命令 |
|
|
| ```bash |
| curl -I https://ohmyapi-c2api.hf.space/ |
| curl https://ohmyapi-c2api.hf.space/health |
| |
| curl https://ohmyapi-c2api.hf.space/v1/models \ |
| -H "Authorization: Bearer $CLAUDE_API_KEY" |
| |
| curl https://ohmyapi-c2api.hf.space/v1/messages \ |
| -H "Content-Type: application/json" \ |
| -H "Authorization: Bearer $CLAUDE_API_KEY" \ |
| -d '{ |
| "model": "claude-sonnet-4-6", |
| "max_tokens": 32, |
| "messages": [{"role": "user", "content": "Reply with exactly: ok"}] |
| }' |
| ``` |
|
|
| 如果最后一条返回正常消息体,就说明当前公开 Space、app token、以及 Claude session 这三层链路都已经打通。 |