中文 | English
独立的 OpenCode Go 多账号额度看板,可部署为 Docker 容器或 Cloudflare Worker,提供 Web 管理后台、加密 Key 存储和真实模型请求测试。不依赖 DeepSeek Harness、Cordis、Typert 或本机 OpenCode 客户端。
Important
本仓库是基于 yascitom/dsh-opencode-go-box v0.3.2 的 Fork 和独立改造,不是上游官方续作,也不代表上游作者或 OpenCode 官方。来源、改造范围、责任边界和免责声明见 NOTICE.md,许可条款见 LICENSE。
- 在
/admin添加、编辑、启停和删除多个 OpenCode Go API Key。 - 每个 Key 可设置持久化分组;后台支持按分组筛选,并按分组名称升序或降序排列。未填写分组的旧数据会显示在“未分组”区块。
- 每个 Key 资产节点都可以单独点击“刷新额度”,只强制查询该 Key,不会刷新其他账号;“测试模型”仍是发送真实模型请求的独立操作。
- Key 资产节点使用独立边框和间距清晰分组;支持逐项选择、全选当前筛选结果和批量删除,环境变量 Key 始终保持只读且不会被选中。
- 支持批量选择多个 Key,点击“批量测试模型”后先选择模型,再为每个 Key 逐一发送真实请求;单个 Key 失败不会中断其他测试,并在对应节点显示独立结果和批量汇总。
- 模型实测会明确区分上游拒绝 Key(401)、当前 Key 无权调用模型(403)、限流或额度耗尽(429)、请求超时、服务不可达和模型返回异常,不再将不同原因统一显示为“Key 无效”。
- 每个账号显示 5 小时、7 天和 30 天窗口的剩余百分比、已用百分比及重置时间。
- 后台支持按秒或分钟设置自动刷新,设置保存在当前浏览器。
- 从官方模型列表选择模型,再发送最小真实请求测试 Key 是否可调用。
- Docker 使用 scrypt + AES-256-GCM 加密文件;Workers 使用 HKDF-SHA256 + AES-256-GCM 加密后保存到 D1。
- 浏览器使用账号密码登录页和 HttpOnly 会话 Cookie;Basic Auth 仍兼容命令行和旧客户端。
- 管理员可创建、编辑、停用和删除查看用户,并逐个分配可查询的 Key;未授权用户不会收到任何账号或额度数据。
- 后台可下载加密账号与用户备份,也可上传备份恢复。
- 每个 Key 可设置开通日期和结束日期,也可选择一个日历月后到期自动删除。
- 提供中文和英文界面,支持
linux/amd64和linux/arm64镜像。
OpenCode Go /zen/go/v1/usage 接口返回的是用量百分比,不是货币余额。接口字段 usage.*.percent 表示已用比例;本项目按 100 - percent 计算并显示剩余比例。例如接口返回 percent: 52 时,后台显示“已用 52%,剩余 48%”。
三个窗口的含义不同:5 小时是滚动窗口,7 天和 30 天是周期窗口。resetsAt 是对应窗口的重置时间,不代表 Key 添加时间或订阅开通时间。接口没有公开货币余额字段,本项目不会根据固定套餐金额推算余额;如果上游调整字段含义,应以原始接口响应和官方页面为准。
后台添加或编辑 Key 时可设置:
开通日期:日期未到时账号显示“待开通”,不会查询额度或发送模型测试请求。结束日期:到达该日期时账号失效。未开启自动删除时,账号仍保留在后台并显示“已到期”。一个月到期自动删除:以开通日期为起点计算一个日历月,到期后删除 Key 和对应额度缓存。例如 1 月 31 日会计算为 2 月最后一天。
日期按 YYYY-MM-DD 保存并以 Asia/Shanghai 日期为准。Docker 进程和 Cloudflare Workers Cron 都每分钟清理一次;受平台调度影响,实际删除可能有短暂延迟。旧账号和旧备份升级后默认使用原添加日期作为开通日期,并保持“不过期、不自动删除”。自动删除属于不可恢复操作,生产环境应先下载加密备份并单独保管原 KEY_ENCRYPTION_SECRET。
添加或编辑 Key 时可以填写分组名称(最多 60 个字符,不能包含换行)。分组保存在 Docker 加密文件或 Workers D1 中,不会因为刷新页面、重启容器、自动刷新或备份恢复而丢失。后台列表提供“全部分组”筛选和三种排序方式:默认顺序(按分组区块显示,组内保持原账号顺序)、分组升序、分组降序;未分组始终排在最后。环境变量注入的只读 Key 不属于任何分组。
升级已有 Workers 部署时,必须先备份 D1 并执行新的远程迁移(0006_account_groups.sql),再部署新代码;旧 D1 数据会自动兼容为“未分组”。
环境变量 WEB_USERNAME / WEB_PASSWORD 是首次部署的系统管理员凭据。管理员首次在 /profile 保存账号或密码后,系统会将管理员凭据加密持久化;管理员仍拥有 Key、用户、测试和备份的全部权限。Key 在 /admin 管理,普通查看用户和账号授权在独立的 /users 页面管理。
- 管理员可添加、修改、停用和删除普通用户,也可重置其用户名、密码和可查询账号。
- 普通用户只能访问看板和
/profile,不能访问/admin、/users或任何/api/admin/*接口。 - 普通用户可在
/profile输入当前密码后修改自己的用户名或密码;修改成功后其他旧会话立即失效。 /api/accounts只返回当前用户已授权且处于可用状态的账号。/api/usage会再次校验账号授权,手动修改账号 ID 不能越权查询。- 未分配账号时返回空列表,页面显示“暂未授权任何账号”,不会回退到任意全局账号。
- 用户被停用、删除、改名或重置密码后,旧会话在下一次请求时立即失效,重新启用账号也不会恢复旧会话。
- 管理员和普通用户均可在
/profile验证当前密码后修改账号或密码。管理员更新后,所有旧管理员会话会立即失效;管理员不能被删除。 - 管理员凭据保存后,环境变量默认不再能登录。忘记管理员凭据时,临时设置
WEB_ADMIN_RECOVERY=1并重新启动 Docker 或重新部署 Worker,即可用WEB_USERNAME/WEB_PASSWORD登录并重设;恢复完成后必须移除此设置或改回0。 - Docker 密码使用 scrypt 加盐哈希并存入 AES-256-GCM 加密文件;Workers 使用每用户随机盐和由
KEY_ENCRYPTION_SECRET派生的 HKDF/HMAC-SHA256 校验值保存在 D1。接口和备份页面不会返回密码或密码哈希。
推荐使用 GitHub Container Registry 上的镜像:
ghcr.io/huiyio/dsh-opencode-go-box:latest
要求服务器已安装 Docker Engine 和 Docker Compose v2。
git clone https://github.com/huiyio/dsh-opencode-go-box.git
cd dsh-opencode-go-box
cp .env.example .envLinux:
openssl rand -base64 48Windows PowerShell:
[Convert]::ToBase64String([Security.Cryptography.RandomNumberGenerator]::GetBytes(48))编辑 .env,至少填写:
IMAGE_TAG=latest
WEB_USERNAME=admin
WEB_PASSWORD=替换成强密码
KEY_ENCRYPTION_SECRET=粘贴上一步生成的随机值
PORT=3000KEY_ENCRYPTION_SECRET 至少 32 个字符。添加 Key 后不要更换它,否则已有加密数据无法解密,服务会拒绝启动。
chmod 600 .env
docker compose pull
docker compose up -d检查状态:
docker compose ps
docker compose logs --tail=100
curl http://127.0.0.1:3000/healthz访问:
- 看板:
http://服务器地址:3000/ - Key 管理:
http://服务器地址:3000/admin - 用户管理:
http://服务器地址:3000/users - 个人设置:
http://服务器地址:3000/profile
浏览器会要求输入 .env 中的 WEB_USERNAME 和 WEB_PASSWORD。首次访问会打开登录页,成功后使用 HttpOnly 会话 Cookie,不再依赖浏览器原生 Basic Auth 弹窗;Basic Auth 仍可用于脚本请求和旧客户端。/healthz 专门用于容器健康检查,不要求认证。
首次管理员登录后可进入 /profile 修改账号或密码。此操作会建立独立的系统管理员凭据,并使旧会话失效;之后 .env 中的登录凭据只在 WEB_ADMIN_RECOVERY=1 时作为紧急恢复入口。
Workers 版与 Docker 版并存,复用同一套 Web UI 和 HTTP API,但运行时和 Key 存储互相独立。Docker 中已有的 /data/keys.enc.json 不会自动迁移到 D1;部署 Worker 后需要在 /admin 重新添加 Key。
要求 Node.js 22、Cloudflare 账号和 Wrangler 登录权限。Fork 本仓库后执行:
npm ci
npx wrangler login
npx wrangler d1 create opencode-go-balance首次创建 D1 后,将命令返回的 database_id 写入 wrangler.jsonc 的 d1_databases[0],然后初始化远程数据库:
npx wrangler d1 migrations apply opencode-go-balance --remote已有 Workers 部署升级时也必须先执行上述远程迁移,再部署新代码。生命周期清理由 wrangler.jsonc 中每分钟运行的 Cron 触发,同时也会在看板和管理 API 请求前执行。
配置三个必需 Secret。命令会在终端中安全提示输入,不要把实际值写进 wrangler.jsonc 或提交到 Git:
npx wrangler secret put WEB_USERNAME
npx wrangler secret put WEB_PASSWORD
npx wrangler secret put KEY_ENCRYPTION_SECRET仅在管理员网页凭据丢失时,再临时设置 WEB_ADMIN_RECOVERY 为 1 并重新部署;恢复完成后将其删除或设为 0,不要把它长期保留为 Worker Secret。
也可以生成一套随机强凭据并批量上传。生成文件已被 Git 忽略,包含登录密码和解密 D1 Key 所需的主密钥,必须作为敏感备份保管:
npm run worker:credentials
npx wrangler secret bulk worker-credentials.jsonKEY_ENCRYPTION_SECRET 至少 32 个字符,添加 Key 后不得更换。可选的只读环境账号可通过 npx wrangler secret put OPENCODE_GO_API_KEY 配置。
部署并检查:
npm run worker:dry-run
npx wrangler deploy
curl https://你的-worker地址/healthz- 看板:
https://你的-worker地址/ - Key 管理:
https://你的-worker地址/admin - 用户管理:
https://你的-worker地址/users - 个人设置:
https://你的-worker地址/profile - 当前部署也绑定了自定义域名:
https://go.llmhost.net/和https://go.llmhost.net/admin。wrangler.jsonc中的custom_domain会让 Cloudflare 自动创建 DNS 记录并签发证书。 /healthz、登录页面、登录脚本和样式可匿名加载;登录接口用于建立会话。看板、后台和管理 API 需要会话 Cookie 或 Basic Auth。Workers 自动提供 HTTPS;仍应使用强密码。需要更严格的身份策略时可在外层再配置 Cloudflare Access。
本地开发可复制 .dev.vars.example 为 Git 忽略的 .dev.vars,填写测试凭据后运行:
npm run worker:d1:local
npm run worker:devWorkers 版的账号、加密 Key、用户权限和用量缓存存储在 D1。升级已有部署时,先备份 D1,再执行迁移和部署:
也可以直接在 /admin 点击“下载备份”保存 JSON 文件,或点击“恢复备份”选择之前下载的文件。新版完整备份包含账号、加密 Key、普通用户、系统管理员密码校验值和授权关系,其中用户部分再次使用 KEY_ENCRYPTION_SECRET 加密。恢复会覆盖当前部署中的全部账号、用户和系统管理员凭据,并清空用量缓存;仍兼容旧版仅账号备份。Docker 和 Workers 备份格式不互通。
npx wrangler d1 export opencode-go-balance --remote --output opencode-go-balance-backup.sql
npx wrangler d1 migrations apply opencode-go-balance --remote
npx wrangler deploy还必须单独安全备份 KEY_ENCRYPTION_SECRET;只有 D1 导出文件或只有主密钥都无法恢复 Key。
GitHub Actions 在以下情况自动构建并发布镜像:
- 推送到
main:发布latest和sha-<提交短哈希>。 - 推送
v*标签:同时发布版本号标签。 - 在 Actions 页面手动运行工作流。
镜像包含 linux/amd64 和 linux/arm64,并附带构建来源证明和 SBOM。
生产环境建议固定 IMAGE_TAG=sha-<提交短哈希>,验证后再升级。查看可用标签:
https://github.com/huiyio/dsh-opencode-go-box/pkgs/container/dsh-opencode-go-box
更新到 .env 指定的标签:
docker compose pull
docker compose up -d
docker compose ps回滚时将 .env 的 IMAGE_TAG 改为之前使用的 sha-* 标签,再执行相同命令。数据卷不会因更换容器镜像而删除。
| 变量 | 默认值 | 说明 |
|---|---|---|
IMAGE_TAG |
latest |
Compose 拉取的 GHCR 镜像标签。 |
WEB_USERNAME |
空 | Web 登录用户名;Compose 部署必填。 |
WEB_PASSWORD |
空 | Web 登录密码;Compose 部署必填。 |
WEB_ADMIN_RECOVERY |
0 |
仅在忘记网页管理员凭据时临时设为 1,允许环境变量管理员恢复登录。恢复后应立即改回 0。 |
KEY_ENCRYPTION_SECRET |
空 | Key 存储主密钥,至少 32 字符;Compose 部署必填。 |
OPENCODE_GO_API_KEY |
空 | 可选的只读环境变量账号,也可在后台添加账号。 |
PORT |
3000 |
宿主机发布端口;容器内固定为 3000。 |
DATA_DIR |
/data |
容器内加密数据目录。 |
FETCH_TIMEOUT_MS |
15000 |
上游请求超时。 |
CACHE_TTL_MS |
30000 |
每个账号的成功用量响应缓存时间。 |
REFRESH_INTERVAL_MS |
30000 |
前台看板自动刷新间隔,最小 10 秒。后台间隔在页面上设置。 |
WARN_PERCENT |
60 |
已用比例达到该值时显示警告。 |
DANGER_PERCENT |
85 |
已用比例达到该值时显示危险。 |
OPENCODE_USAGE_URL |
官方用量接口 | 一般无需修改。自定义地址会接收账号 Bearer Key,只能使用可信服务。 |
OPENCODE_MODEL_TEST_URL |
官方模型接口 | 模型测试请求地址。 |
OPENCODE_MODEL_LIST_URL |
官方模型列表 | 测试弹窗的模型列表地址。 |
OPENCODE_MODEL_TEST_MODEL |
hy3 |
未提供模型时的兼容默认值;后台正常流程由用户选择。 |
Compose 使用固定命名卷 opencode-go-balance-data,Key 数据位于卷内的 /data/keys.enc.json。
备份数据卷:
mkdir -p backup
docker run --rm \
-v opencode-go-balance-data:/data:ro \
-v "$PWD/backup:/backup" \
alpine:3.22 sh -c 'tar -C /data -czf /backup/opencode-go-data.tgz .'必须同时备份 .env 中的 KEY_ENCRYPTION_SECRET。数据文件和加密主密钥缺少任意一个都无法恢复 Key,不要将它们存放在同一个公开位置。
恢复前停止服务,并确保使用原来的 KEY_ENCRYPTION_SECRET:
docker compose down
docker volume create opencode-go-balance-data
docker run --rm \
-v opencode-go-balance-data:/data \
-v "$PWD/backup:/backup:ro" \
alpine:3.22 sh -c 'tar -C /data -xzf /backup/opencode-go-data.tgz'
docker compose up -ddocker compose down 不会删除数据卷;不要使用 docker compose down -v,除非明确要永久删除所有账号数据。
预构建镜像不可用或需要审核修改时,可以本地构建:
docker build -t opencode-go-balance-web:local .
docker volume create opencode-go-balance-data
docker run -d \
--name opencode-go-balance \
--restart unless-stopped \
--env-file .env \
-p 3000:3000 \
-v opencode-go-balance-data:/data \
opencode-go-balance-web:local本地开发需要 Node.js 22 或更高版本:
npm run check
npm test
npm run previewnpm run preview 只监听 127.0.0.1:57726,并在 Git 忽略的 .local-runtime 中保存本地预览数据,不代替正式 Docker 或 Workers 部署。
GET / Web 看板
GET /admin Key 管理后台
GET /users 用户和账号授权管理
GET /profile 当前用户个人设置
GET /api/me 当前登录身份、角色和凭据类型
PATCH /api/me 当前登录用户验证当前密码后修改用户名或密码
GET /api/accounts 可用账号元数据
GET /api/usage?account=<id> 指定账号额度(加 `&refresh=1` 强制绕过该账号缓存)
GET /api/admin/users 用户与账号授权列表
POST /api/admin/users 添加普通用户
PATCH /api/admin/users/<id> 编辑用户、重置密码、启停或修改授权
DELETE /api/admin/users/<id> 删除用户并立即使会话失效
GET /api/admin/accounts 全部账号元数据
GET /api/admin/models 测试弹窗可选模型
GET /api/admin/backup 下载加密账号与用户备份
POST /api/admin/restore 恢复加密账号与用户备份
POST /api/admin/accounts 添加账号
PATCH /api/admin/accounts/<id> 编辑、换 Key 或启停
DELETE /api/admin/accounts/<id> 删除账号
POST /api/admin/accounts/<id>/test 按所选模型发送最小测试请求
POST /api/admin/accounts/batch-test 批量按所选模型逐一发送真实测试请求
GET /healthz 匿名健康检查
除 /healthz、/login 和登录接口外,所有页面和接口都受会话 Cookie 或 Basic Auth 保护。普通用户只获得被授权账号的只读额度接口;管理员接口在服务端校验角色。所有 Key 相关响应只返回掩码,不返回明文;备份文件也只包含加密密文。
- 公网部署必须在容器前配置 HTTPS 反向代理;Basic Auth 在纯 HTTP 下不会加密密码。
- 镜像以非 root 用户运行;Compose 使用只读根文件系统、丢弃 Linux capabilities 并禁止提权。
- 只有
/data数据卷可写,API Key 不会写入镜像、浏览器响应或应用日志。 - “测试模型”会发送真实模型请求,可能消耗额度并触发限流;只有用户确认后才会发送。
- 恢复备份会覆盖当前账号和用户列表,执行前应确认备份来源和主密钥;额度缓存会在恢复后清空。
- Workers Secret、
worker-credentials.json、.dev.vars、D1 导出文件和 Docker.env都不得提交到 Git;日志和响应不会输出完整 Key。 - OpenCode Go 接口格式或地址未来可能变化,生产使用者应自行监控。
本 Fork 与上游作者、OpenCode、DeepSeek 或 DeepSeek Harness 没有官方隶属或背书关系。上游代码问题和本 Fork 的 Docker/Web 改造问题应分别向对应仓库反馈。完整说明见 NOTICE.md。
本项目依据 MIT License 按“原样”提供,不作任何明示或默示担保。