c2api / README.md
ohmyapi's picture
Polish README for simple-mode HF deployment
8b4dc02 verified
metadata
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_HOSTDB_PORTDB_USERDB_PASSDB_NAMEPGSSLMODE
  • 当前根路径 / 会直接 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

直接注入成容器进程的真实运行时环境变量。

对这个仓库来说,等价于容器启动时直接拿到了例如:

ADMIN_USER=admin
LISTEN_ADDR=:7860
CLAUDE_API_KEY=...
ADMIN_PASS=...
CLAUDE_SESSION_KEYS=...

因此,只要上游 claude2api 在启动时通过 os.Getenv(...) 或等价方式读取配置,它就会直接生效,不需要额外写入 .envconfig.yaml 或其它文件。

当前已确认的 Space Variables

当前公开可读到的 Variables 是:

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 = Nonestorage.requested = None,因此容器内本地 PostgreSQL 不能视为正式持久化层。

  3. 对当前上游镜像的排查显示,DB-only 路径很可能会把 PostgreSQL DSN 拼成:

    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

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 中运行

最小验收命令

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 这三层链路都已经打通。