ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

TaoToken 给 OPENCODE_SERVER_PASSWORD 补位,OpenCode Web 端别裸奔

TaoToken 给 OPENCODE_SERVER_PASSWORD 补位,OpenCode Web 端别裸奔 在开发机上跑起opencode serve之后很多人第一件事是掏出手机或另一台电脑用浏览器打开http://内网IP:4096想看看 Agent 改到哪一步了。能打开能操作感觉很爽。但这里有个默认行为值得警惕OPENCODE_SERVER_PASSWORD为空时这个 HTTP 服务不做认证同一网段里任何人访问这个地址都能看到你的会话列表、文件树甚至切到 Build 模式直接驱动 Agent 改代码、跑 shell。这不是配置疏漏是开箱默认状态。要堵住这个口子同时又不让模型调用凭据散落到十几个配置文件里可以在 TaoToken 官网 统一取 Key再把 Base URL 设为https://taotoken.net/api填进模型 provider。下面按服务密码和模型 Key两条线拆开讲给出可直接复制的命令、验证方法和存放位置对照。1. OpenCode 的客户端-服务器架构决定了 Web 端是一道真实的门OpenCode 和普通的 IDE 插件不一样它的核心设计是客户端-服务器后端常驻本机终端 TUI、桌面端、浏览器 Web、IDE 插件都只是接入这个服务的客户端。这个设计的收益很直接代码不用离开本机一套服务可以多终端同时接入会话你甚至可以在外面用手机接回家里的开发机继续推进任务。代价也在这个架构上。既然服务是一个 HTTP 端口那它就具备了一切网络服务的攻击面谁监听了这个端口谁就拥有这个服务端口绑到0.0.0.0时局域网内任何设备都能连没有认证时连上等于完全控制因为 OpenCode 的 Build 模式本身就有文件写入和命令执行权限。把这两件事叠起来看就很清楚了一个默认无密码的、能执行 shell 的 HTTP 服务暴露在共享办公网、咖啡厅 Wi-Fi、宿舍路由器下面风险等级和把 SSH 开着无密码登录差不多。所以加固思路应该分两层而不是只做一层接入层用OPENCODE_SERVER_PASSWORD给 HTTP 服务加一道 Basic Auth解决谁能连进来。凭据层把模型 API Key 从明文配置里挪到环境变量并统一从一个可控的入口获取解决连进来之后能用什么、Key 泄露了怎么办。这两层经常被混为一谈。下面先把边界讲清楚。2. 两把钥匙不要混服务密码与模型 API Key 的边界OPENCODE_SERVER_PASSWORD和模型 API Key 是两套完全独立的认证体系作用点不同泄露后果也不同。第一把钥匙OPENCODE_SERVER_PASSWORD它保护的是 OpenCode 本地 HTTP 服务的入口。设置之后浏览器、IDE 插件、远程客户端访问服务时需要通过 Basic Auth 校验默认用户名是opencode密码就是你设置的值。它不参与任何模型调用只决定谁能操作这个本地服务。第二把钥匙模型 Provider 的 API Key它保护的是模型额度。OpenCode 作为调用方拿着这个 Key 去模型供应商那边请求推理。它决定这次对话要花谁的钱、走谁的通道。两者为什么必须分开管因为泄露路径不一样服务密码泄露攻击者可以操作你本机的仓库和 shell这是最严重的一档模型 Key 泄露攻击者可以消耗你的额度甚至通过 prompt 反推你的业务内容如果 Key 明文写在opencode.json里那么任何能连上 Web 端的人都有可能通过界面或配置读到它两道门就变成了一道。把 Key 放在环境变量里、并且只在一个地方集中管理是更稳妥的做法。模型调用这一侧可以直接用 TaoToken 作为统一入口到 TaoToken 官网 注册后创建 KeyBase URL 固定填https://taotoken.net/apiOpenCode、Claude Code、Codex 走同一个出口轮换 Key 时只改一处。凭据保护对象建议存放位置是否进 GitOPENCODE_SERVER_PASSWORD本地 OpenCode HTTP 服务shell profile、systemd EnvironmentFile权限 600否模型 API Key模型调用额度系统环境变量 / 密钥管理工具否opencode.json行为策略provider、权限~/.config/opencode/或项目根目录全局配置可提交含密钥的不可提交.env本地临时变量项目根目录且被 OpenCode 默认拒绝读取否3. 设置 OPENCODE_SERVER_PASSWORD 的三条落地路径先给一个最小可用的命令组合确认能跑通再谈持久化。# 1) 生成一个足够强的密码不要手敲 openssl rand -base64 24 # 2) 设置服务密码与用户名用户名可省略默认 opencode export OPENCODE_SERVER_USERNAMEopencode export OPENCODE_SERVER_PASSWORD把上一步生成的字符串粘到这里 # 3) 启动服务。要远程访问才绑 0.0.0.0只本机用就绑 127.0.0.1 opencode serve --hostname 0.0.0.0 --port 4096这里有个容易忽略的取舍如果你只在本机用 TUI绑127.0.0.1就够了甚至可以完全不设密码因为外部网络根本连不进来。但只要你打算用手机、平板或第二台机器接入就必须绑0.0.0.0而一旦绑了OPENCODE_SERVER_PASSWORD就不是可选项。路径一shell profile 持久化适合个人开发机把变量写进~/.zshrc或~/.bashrc注意文件权限不要让同机器其他用户读到。# 追加到 ~/.zshrc echo export OPENCODE_SERVER_USERNAMEopencode ~/.zshrc echo export OPENCODE_SERVER_PASSWORD你的密码 ~/.zshrc chmod 600 ~/.zshrc source ~/.zshrc路径二systemd 用户服务适合常驻后台常驻服务用 systemd 管密码不要直接写在 unit 文件里用EnvironmentFile单独放权限压到 600。# ~/.config/systemd/user/opencode-server.service [Unit] DescriptionOpenCode local server Afternetwork.target [Service] Typesimple EnvironmentOPENCODE_SERVER_USERNAMEopencode EnvironmentFile%h/.config/opencode/server.env ExecStart%h/.local/bin/opencode serve --hostname 0.0.0.0 --port 4096 Restarton-failure [Install] WantedBydefault.target# ~/.config/opencode/server.env只写一行 OPENCODE_SERVER_PASSWORD你的密码 chmod 600 ~/.config/opencode/server.env systemctl --user daemon-reload systemctl --user enable --now opencode-server用这种方式的好处是改密码不用动 service 文件重启服务即生效也不会有密码残留在history或进程列表里。路径三Windows 用户级环境变量适合 PowerShell 用户Windows 下curl | bash那套不适用环境变量用下面两句设置设置完需要重开终端。[Environment]::SetEnvironmentVariable(OPENCODE_SERVER_USERNAME,opencode,User) [Environment]::SetEnvironmentVariable(OPENCODE_SERVER_PASSWORD,你的密码,User)三条路径选一条即可不要同时设置否则排查时很难判断进程到底读到了哪个值。4. 访问验证怎么确认密码真的生效了设置环境变量和认证生效之间隔着一整条链路必须实测。推荐按下面的顺序验证。第一步本机不带凭据请求应该被拒绝curl -i -m 5 http://127.0.0.1:4096/期望看到类似HTTP/1.1 401 Unauthorized和WWW-Authenticate: Basic的响应头。如果直接返回 200 或正常页面内容说明密码没生效。第二步带凭据请求应该能通过curl -i -m 5 -u opencode:你的密码 http://127.0.0.1:4096/第三步从另一台机器验证边界# 把 IP 换成开发机内网地址 curl -i -m 5 http://192.168.1.20:4096/这一步要确认两件事一是能连通但返回 401二是如果连不通连接超时说明你绑的是127.0.0.1或者被防火墙拦了这其实是更安全的默认状态只是远程接入需要额外放行。第四步浏览器侧确认浏览器访问http://192.168.1.20:4096应弹出 Basic Auth 输入框。如果没弹而直接进入界面回到第一步重新检查。密码设置了却不生效通常是这几个原因先启动服务、后export的进程读到的还是旧环境重启服务即可在 A 终端设置在 B 终端启动两个 shell 环境不互通systemd 的EnvironmentFile路径写错或权限不对服务静默用了空密码前面挂了反向代理把Authorization头吃掉了用了opencode之外的启动方式比如某个 IDE 插件自己拉起进程没有继承你的环境变量。排查这类问题最直接的方式是打印进程环境确认# 先查进程 PID pgrep -af opencode # Linux 下确认环境变量是否被继承 tr \0 \n /proc/PID/environ | grep OPENCODE_SERVER看到密码字段是空值就说明问题在启动环节不在 OpenCode 本身。5. 模型这一侧把 Provider 指向 TaoToken 并让 Key 走环境变量服务门锁上了接下来处理模型调用。OpenCode 的 provider 配置写在opencode.json里全局路径通常是~/.config/opencode/opencode.json项目级就是仓库根目录。推荐用全局配置把 Key 通过环境变量注入而不是写死在 JSON 里。先取 Key。到 TaoToken 官网 完成注册并创建 API Key然后在开发机上把它设成环境变量# 写入 shell profile避免每次手动 export echo export TAOTOKEN_API_KEYYOUR_API_KEY ~/.zshrc source ~/.zshrc接着配置 provider。OpenCode 通过 npm 包来加载兼容 OpenAI 协议的 provider配置大致如下{ $schema: https://opencode.ai/config.json, provider: { taotoken: { npm: ai-sdk/openai-compatible, name: TaoToken, options: { baseURL: https://taotoken.net/api, apiKey: {env:TAOTOKEN_API_KEY} }, models: { your-model-id: { name: Your Model } } } }, model: taotoken/your-model-id }这里有几个点必须注意第一baseURL不要带 UTM 参数。它是工具调用的接口地址固定写https://taotoken.net/api后缀参数会污染请求路径。第二apiKey用{env:TAOTOKEN_API_KEY}这种引用写法。这样 Key 只存在于系统环境变量里opencode.json可以放心提交到团队仓库不会把密钥带出去。第三模型 ID 格式必须是provider/modelId。上面的taotoken/your-model-id需要替换成你在控制台模型列表里看到的真实 ID照抄名字写错会直接报ProviderModelNotFoundError这个报错基本都是在说provider 前缀或者模型 ID 拼错了。第四models里声明的 ID 要和最终model字段拼出来的后半段一致。有人只改了顶层model却忘了在models里补声明结果就是模型列表为空。改完配置后重启 OpenCode 服务再在 TUI 里发一条消息确认走的是 TaoToken 通道。如果报鉴权失败先确认环境变量在当前 shell 里可见test -n $TAOTOKEN_API_KEY echo key loaded || echo key missing6. 其他客户端的 Key 存放位置对照别把变量名串了同一个 TaoToken Key在不同工具里的配置形态完全不同。最容易出的事就是把 Claude Code 的ANTHROPIC_*变量名照搬给 Codex结果 Codex 完全不认还会以为是 Key 失效。Claude Codesettings.json里走env字段{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_AUTH_TOKEN: YOUR_API_KEY } }Codexconfig.toml里声明 providermodel_provider taotoken model your-model-id [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api responses注意 Codex 走的是model_providers段落加env_key的机制它读的是TAOTOKEN_API_KEY这个自定义变量不是ANTHROPIC_*。两套体系的字段名、段落结构都不一样互相套用必然失败。CC Switch三件套对应关系在 CC Switch 里切换供应商时本质上是填三个值Base URL、API Key、模型名。对应到 TaoToken 就是字段填写内容Base URLhttps://taotoken.net/apiAPI Key控制台创建的 Key即YOUR_API_KEY模型控制台模型列表里的真实 ID把这张表和前面的opencode.json、settings.json、config.toml放在一起看规律很清晰接入地址和凭据是常量配置语法是变量。换工具时改语法不要改地址和 Key 的语义。7. 加固清单把服务密码、权限沙盒和 Key 管理一次性配齐前面讲的是要做的事这一节把顺序和检查项固化下来适合照着逐条核对。服务侧OPENCODE_SERVER_PASSWORD必须非空密码用openssl rand -base64 24生成不要用生日和项目名只在需要远程接入时绑0.0.0.0否则优先127.0.0.1密码存放文件权限设 600不进 Git不进聊天记录修改密码后必须重启服务并用第 4 节的curl命令复验。权限侧OpenCode 的权限沙盒配置写在opencode.json里可以对文件编辑、shell 执行、外部抓取分别设定策略。默认保守一点需要时再逐条放开{ permission: { edit: ask, bash: { *: ask, git status: allow, git diff: allow }, webfetch: ask } }要理解一点Plan 模式只是默认只读不是安全屏障。手动改权限就能放开写操作所以真正的边界在配置和密码上不在模式名上。Key 侧.env和.env.*默认被拒绝读取这是保护机制不要为了图方便去改其他敏感文件比如生产配置、证书私钥要在 permission 里显式denyAPI Key 只放环境变量配置文件中一律用{env:...}引用Key 需要轮换时改一处环境变量并重启服务比翻十几个配置文件可靠得多。流程侧服务密码和模型 Key 分开轮换互不影响出问题时也更容易定位是哪一层失效团队共享开发机时每个人用自己的系统账号和服务实例不要共用同一个OPENCODE_SERVER_PASSWORD。8. 写在最后OpenCode 的价值在于把模型选择权、运行环境选择权、代码数据控制权交回开发者手里但本地可控这四个字不是自动成立的它取决于你有没有把默认开放的那道门关上。OPENCODE_SERVER_PASSWORD是服务入口的门锁模型 API Key 的存放方式是凭据管理的门锁两把锁各自独立缺任何一个都不算完整加固。实际落地时整套动作可以压缩成四步生成强密码并注入服务环境、绑好监听地址、用curl复验 401、把模型 provider 的 Base URL 指向https://taotoken.net/api并让 Key 走环境变量。做完这四步Web 端接入才算既方便又不裸奔。需要动手时可以从下面几个入口按顺序走先用模型对话确认模型通道可用再看 Coding Plan 了解适合持续编码场景的方案接着到创建 API Key拿到YOUR_API_KEY最后参照 Claude Code 文档里的配置格式把同一套接入方式迁移到其他编码工具上做到一处取 Key、多端复用。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进