ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

部 Codex 到内网 Runner,TaoToken 只留 API 入口

部 Codex 到内网 Runner,TaoToken 只留 API 入口 1. 内网 Runner 部署 Codex先把 TaoToken 作为唯一 API 入口Codex 的产品侧最近因为 OpenAI 引入 Linear 产品负责人余楠而再次成为话题。但对私有化部署工程师来说更现实的问题是Codex 到底怎么放进内网 Runner让它在受控环境里执行任务而模型调用只留一个 API 入口。我的做法是Runner 上只保留TAOTOKEN_API_KEY和 Base URLhttps://taotoken.net/api其余全部走内网策略。Key 在 TaoToken 官网 获取。本文给出一套可复现的 Runner 环境变量、config.toml、systemd 服务、任务日志和排障清单。目标不是讨论 Codex 未来会变成什么产品而是让今天的内网 Runner 能稳定执行任务并且只通过一个外部 API 入口访问模型能力。TaoToken 在这个方案里只承担两件事提供 API Key提供 Base URL。至于仓库读写、命令执行、测试运行、制品上传全部留在内网 Runner 的权限边界内。这样做的直接好处是开发机不需要安装 Codex CLI不需要把长期 Key 散落在个人电脑上模型调用统一从 Runner 出口出去审计、限流、日志脱敏都有地方落。下面从拿到 Key 开始一步步把配置写进 Runner。2. 拿到 Key 后config.toml 里只写 provider 和 Base URLCodex 的配置和 Claude Code 是两条线。Codex 用~/.codex/config.tomlClaude Code 用settings.json和ANTHROPIC_*环境变量。把ANTHROPIC_*套到 Codex 是常见错误结果就是 Codex 读不到 Key或者请求发到了错误端点。正确顺序是先在 TaoToken 官网 创建 API Key拿到以sk-开头的字符串然后确认 Base URL 是https://taotoken.net/api。注意这个地址在 Codex 配置里作为 provider 的base_url使用不要再手动拼/v1也不要加末尾斜杠。模型 ID 以 TaoToken 控制台当前可用列表为准下面示例用占位形式部署时替换成你的实际模型名。在 Runner 的专用用户目录下创建配置sudo -u runner mkdir -p /var/lib/codex-runner/.codex sudo -u runner chmod 700 /var/lib/codex-runner/.codex sudo -u runner touch /var/lib/codex-runner/.codex/config.toml sudo -u runner chmod 600 /var/lib/codex-runner/.codex/config.toml写入config.toml# /var/lib/codex-runner/.codex/config.toml model gpt-5-codex # 替换为 TaoToken 控制台里可用的模型 ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEY wire_api responses # 如果当前 Codex 版本只支持 chat可改为 chat [profiles.default] model gpt-5-codex model_provider taotoken这里的关键点有三个。第一env_key写的是TAOTOKEN_API_KEY不是OPENAI_API_KEY。第二base_url固定为https://taotoken.net/api不携带 UTM 参数。第三wire_api要和 Codex 版本匹配如果你运行codex --help看到配置说明里用的是chat就改成chat。配置完成后用 Runner 用户执行一次最小调用sudo -u runner env \ HOME/var/lib/codex-runner \ CODEX_HOME/var/lib/codex-runner/.codex \ TAOTOKEN_API_KEYYOUR_API_KEY \ codex exec --json 在当前目录输出一个 hello.txt内容为 hello runner如果返回 JSON 事件流并且退出码为 0说明 Codex 已经能通过 TaoToken 的 API 入口调用模型。此时不要急着把 Key 写进 shell rc下一步要把环境变量放到 Runner 服务层。3. 环境变量注入systemd、GitLab Runner、GitHub Actions self-hosted内网 Runner 的部署方式不同环境变量注入位置也不同。原则只有一个Key 不进入代码仓库不进入制品不进入任务脚本。下面给三种常见形态。3.1 systemd 托管的自定义 Runner如果 Runner 是你自己写的常驻进程用 systemd 管起来最稳。先创建环境文件sudo mkdir -p /etc/taotoken-runner sudo chmod 700 /etc/taotoken-runner sudo tee /etc/taotoken-runner/runner.env /dev/null EOF TAOTOKEN_API_KEYYOUR_API_KEY TAOTOKEN_BASE_URLhttps://taotoken.net/api CODEX_HOME/var/lib/codex-runner/.codex HOME/var/lib/codex-runner LOG_LEVELinfo EOF sudo chmod 600 /etc/taotoken-runner/runner.env sudo chown root:runner /etc/taotoken-runner/runner.env然后写 systemd 服务# /etc/systemd/system/codex-runner.service [Unit] DescriptionInternal Runner for Codex with TaoToken API Afternetwork-online.target Wantsnetwork-online.target [Service] Typesimple Userrunner Grouprunner EnvironmentFile/etc/taotoken-runner/runner.env WorkingDirectory/opt/codex-runner ExecStart/opt/codex-runner/run.sh Restarton-failure RestartSec5 NoNewPrivilegestrue PrivateTmptrue ProtectSystemstrict ProtectHometrue ReadWritePaths/var/lib/codex-runner /var/log/codex-runner /workspace [Install] WantedBymulti-user.target重载并启动sudo systemctl daemon-reload sudo systemctl enable --now codex-runner.service sudo systemctl status codex-runner.service --no-pager检查环境变量是否注入成功但不要把完整 Key 打印到屏幕sudo systemctl show codex-runner.service --propertyEnvironment如果输出里能看到TAOTOKEN_BASE_URLhttps://taotoken.net/api和TAOTOKEN_API_KEY存在但不想暴露值可以用systemctl show后手动截断。更稳妥的方式是在 Runner 内部写一个健康检查任务只校验变量长度和前缀不输出原值。3.2 GitLab RunnerGitLab Runner 用config.toml管理 executor。把环境变量放在[[runners]]的environment字段里# /etc/gitlab-runner/config.toml [[runners]] name codex-internal-runner url https://gitlab.internal.example.com/ token GITLAB_RUNNER_TOKEN executor shell environment [ TAOTOKEN_API_KEYYOUR_API_KEY, TAOTOKEN_BASE_URLhttps://taotoken.net/api, CODEX_HOME/var/lib/codex-runner/.codex, HOME/var/lib/codex-runner ]修改后重启sudo gitlab-runner restart sudo gitlab-runner verify注意 GitLab Runner 的config.toml权限要收紧sudo chown root:root /etc/gitlab-runner/config.toml sudo chmod 600 /etc/gitlab-runner/config.toml3.3 GitHub Actions self-hosted RunnerGitHub Actions self-hosted Runner 支持在 Runner 根目录放.env文件。进入 Runner 安装目录创建或追加cd /opt/actions-runner sudo -u runner tee .env /dev/null EOF TAOTOKEN_API_KEYYOUR_API_KEY TAOTOKEN_BASE_URLhttps://taotoken.net/api CODEX_HOME/var/lib/codex-runner/.codex HOME/var/lib/codex-runner EOF sudo chown runner:runner .env sudo chmod 600 .env然后重启 Runner 服务sudo ./svc.sh stop sudo ./svc.sh start sudo ./svc.sh status在 workflow 里不要写 Key只需要调用codex exec或你的包装脚本# .github/workflows/codex-runner-check.yml name: codex-runner-check on: workflow_dispatch: jobs: codex: runs-on: [self-hosted, linux, codex] steps: - uses: actions/checkoutv4 - name: Run Codex task run: | codex exec --json 读取 README.md 并生成一份变更摘要到 summary.md - name: Show task log tail if: always() run: | tail -n 50 /var/log/codex-runner/latest.log三种方式都只做一件事把 Key 和 Base URL 注入到 Runner 进程。Codex 自己再去读~/.codex/config.toml。不要把ANTHROPIC_*写进这些环境文件那是 Claude Code 的配置。4. 任务日志从 codex exec 的 JSON 事件到脱敏日志私有化部署的验收标准之一是任务失败时你能拿出可追溯的日志。Codex 的--json会输出事件流但我们不能把原始输出直接落盘因为里面可能带 Key、带内部仓库路径、带业务代码片段。建议在 Runner 里加一层包装脚本统一生成任务 ID、记录模型和退出码并对敏感信息做脱敏。创建/opt/codex-runner/run.sh#!/usr/bin/env bash set -euo pipefail LOG_DIR${LOG_DIR:-/var/log/codex-runner} mkdir -p $LOG_DIR chmod 750 $LOG_DIR TASK_ID${TASK_ID:-$(date %Y%m%d-%H%M%S)-$$} LOG_FILE$LOG_DIR/codex-${TASK_ID}.log LATEST_LINK$LOG_DIR/latest.log # 只保留必要变量避免把 Runner 进程里的其他敏感变量传给 Codex env -i \ PATH$PATH \ HOME${HOME:-/var/lib/codex-runner} \ CODEX_HOME${CODEX_HOME:-/var/lib/codex-runner/.codex} \ TAOTOKEN_API_KEY${TAOTOKEN_API_KEY:?TAOTOKEN_API_KEY is required} \ TAOTOKEN_BASE_URL${TAOTOKEN_BASE_URL:-https://taotoken.net/api} \ codex exec --json $ $LOG_FILE 21 EXIT_CODE$? ln -sfn $LOG_FILE $LATEST_LINK # 脱敏常见 Key 形态、Authorization 头、Bearer 片段 sed -i -E \ -e s/(sk-[A-Za-z0-9_-]{8,})/sk-***REDACTED***/g \ -e s/(Authorization: Bearer )[A-Za-z0-9._-]/\1***REDACTED***/g \ -e s/(TAOTOKEN_API_KEY)[A-Za-z0-9._-]/\1***REDACTED***/g \ $LOG_FILE # 追加任务元数据方便 grep { echo --- echo task_id$TASK_ID echo exit_code$EXIT_CODE echo model_providertaotoken echo base_url${TAOTOKEN_BASE_URL:-https://taotoken.net/api} echo finished_at$(date -Iseconds) } $LOG_FILE exit $EXIT_CODE脚本要点TASK_ID由日期和 PID 组成便于从网关日志反查。env -i避免 Runner 进程里的其他变量泄露给 Codex。sed -i做基础脱敏但不要依赖它覆盖所有情况更严格的做法是在采集层用正则过滤。日志文件权限设为750只允许 runner 用户和运维组读取。latest.log用软链接指向最近一次任务方便 workflow 和人工排障。再加一个 logrotate 配置防止 Runner 磁盘被日志打满# /etc/logrotate.d/codex-runner /var/log/codex-runner/*.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 runner runner sharedscripts postrotate find /var/log/codex-runner -name latest.log -type l -delete endscript }验证日志是否可读sudo -u runner tail -n 20 /var/log/codex-runner/latest.log sudo -u runner grep -E task_id|exit_code|base_url /var/log/codex-runner/latest.log如果日志里能看到exit_code0并且base_url是https://taotoken.net/api说明任务链路已经打通。5. 排障401、404、429、超时和证书一条条过内网 Runner 最常见的故障不是模型能力而是网络和配置。下面按错误码和症状给排查顺序。5.1 401 Unauthorized症状Codex 返回401日志里出现invalid api key或missing authorization。排查# 在 Runner 用户下检查变量是否存在 sudo -u runner env | grep -E ^TAOTOKEN_API_KEY | sed s/.*/present/ sudo -u runner env | grep -E ^TAOTOKEN_BASE_URL确认config.toml里env_key TAOTOKEN_API_KEY与环境变量名一致。如果手动用 curl 测试curl -sS -o /dev/null -w %{http_code}\n \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ https://taotoken.net/api如果这里返回 401说明 Key 本身或请求头有问题如果这里返回 200/404但 Codex 仍 401说明 Codex 没有读到正确的config.toml。检查CODEX_HOME是否指向/var/lib/codex-runner/.codex。5.2 404 Not Found症状Codex 请求路径拼接错误日志里出现404或not found。排查Base URL 必须是https://taotoken.net/api不要写成https://taotoken.net/api/v1。不要加末尾斜杠https://taotoken.net/api/可能导致 provider 再拼一次路径。如果wire_api与实际端点不匹配也可能返回 404。先用curl -I https://taotoken.net/api看连通性curl -I https://taotoken.net/api如果内网 DNS 无法解析先解决 DNS 或出口白名单而不是改 Base URL。5.3 429 Too Many Requests症状并发任务多时出现429日志里出现rate limit。排查Runner 侧加队列不要一次性并发几十个 Codex 任务。在包装脚本里加退避重试但只对 429 和 5xx 重试retry_codex() { local max_attempts3 local attempt1 while (( attempt max_attempts )); do if codex exec --json $; then return 0 fi local code$? if [[ $code -eq 429 || $code -ge 500 ]]; then sleep $(( attempt * 5 )) ((attempt)) else return $code fi done return 1 }如果团队规模大考虑在 TaoToken 控制台查看用量和限流策略必要时升级 Coding Plan。入口在文末 CTA 里。5.4 连接超时与 TLS 证书症状timeout、connection refused、x509: certificate signed by unknown authority。排查# DNS getent hosts taotoken.net # 出口连通性 curl -v --connect-timeout 5 https://taotoken.net/api # 企业根证书 openssl s_client -connect taotoken.net:443 -servername taotoken.net /dev/null如果内网要求走企业出口代理在 Runner 环境里设置HTTPS_PROXY和NO_PROXY不要把代理配置写进 Codex 的config.toml。如果使用私有 CA设置SSL_CERT_FILE或把根证书加入系统信任库。注意这些是内网网络策略问题不是 TaoToken 的 API 入口问题。6. Claude Code 与 CC Switch 三件套别把 ANTHROPIC_* 套到 Codex同一个团队往往既跑 Codex也跑 Claude Code。两者共用 TaoToken 的 API 入口但配置文件完全不同。Codex 用config.toml和TAOTOKEN_API_KEYClaude Code 用settings.json和ANTHROPIC_*。如果你用 CC Switch 管理多套 Claude Code 配置记住三件套供应商 Base URL、API Key、模型名。它们分别落在三个地方。第一件~/.claude/settings.json写环境变量{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: YOUR_API_KEY, ANTHROPIC_MODEL: claude-sonnet-4-5 } }第二件shell 或 Runner 环境变量作为 settings.json 的覆盖export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEYYOUR_API_KEY export ANTHROPIC_MODELclaude-sonnet-4-5第三件CC Switch 的供应商配置文件。你可以在 CC Switch 里新增一个 provider字段填{ name: taotoken, base_url: https://taotoken.net/api, api_key_env: ANTHROPIC_API_KEY, models: { default: claude-sonnet-4-5 } }CC Switch 的作用是切换不同供应商但 Key 仍然建议通过环境变量注入不要明文写进仓库。团队共用 Runner 时Codex 和 Claude Code 可以共用同一个TAOTOKEN_API_KEY还是分开从审计角度建议分开创建 KeyCodex 用一组Claude Code 用另一组这样在 TaoToken 控制台能看到各自的调用量。创建入口在 TaoToken 官网 的 API Keys 页面。Claude Code 的详细接入方式可以看文末的 Claude Code 文档链接。再次强调不要把ANTHROPIC_BASE_URL写进 Codex 的config.toml也不要把ANTHROPIC_API_KEY当成 Codex 的env_key。两者混用会导致 Codex 请求发到错误端点或者直接 401。7. 内网安全边界Key、出口、日志和权限私有化部署工程师需要给安全团队一个可解释的边界。这个方案里Codex 在内网 Runner 执行任务但模型调用只走一个出口https://taotoken.net/api。你需要明确以下四点。第一Key 的存放。Runner 环境文件权限600属主root:runner。Key 不写入仓库、不写入任务参数、不写入镜像层。轮换 Key 时只更新/etc/taotoken-runner/runner.env然后systemctl restart codex-runner。第二网络出口。如果内网有防火墙只允许 Runner 所在网段访问taotoken.net:443。不需要开放其他外部地址。DNS 解析建议走内网 DNS避免 Runner 直连公共 DNS。第三日志脱敏。包装脚本已经对sk-前缀和Authorization: Bearer做替换但生产环境还应该在日志采集侧再加一层过滤。如果日志要进 Elasticsearch 或 Loki配置脱敏规则避免 Key 片段被索引。第四文件系统权限。Runner 用户只对/workspace、/var/lib/codex-runner、/var/log/codex-runner有写权限。不要给 Runner 用户 sudo不要让它访问生产数据库。任务里如果涉及 SQL由读者在本地或独立审批环境执行不要让 Runner 直接连生产库。验收清单[ ] Runner 用户能读取 /var/lib/codex-runner/.codex/config.toml [ ] config.toml 中 base_url 为 https://taotoken.net/api [ ] Runner 环境变量中存在 TAOTOKEN_API_KEY但不落盘到仓库 [ ] codex exec --json 最小任务退出码为 0 [ ] /var/log/codex-runner/latest.log 包含 task_id、exit_code、base_url [ ] 日志中未出现完整 sk- Key [ ] 401、404、429 三类错误有对应的排障命令 [ ] Claude Code 的 ANTHROPIC_* 与 Codex 的 config.toml 未混用8. 结语与 CTA把 Runner 跑通再谈规模化把 Codex 放进内网 Runner核心不是模型选择而是配置边界Runner 负责执行TaoToken 只提供 Key 与 Base URL。config.toml里写model_provider taotoken和base_url https://taotoken.net/api环境变量里注入TAOTOKEN_API_KEY任务日志里记录task_id和exit_code排障时按 401、404、429、超时逐项检查。Claude Code 走settings.json和ANTHROPIC_*CC Switch 管理供应商、Key、模型三件套不要和 Codex 混用。这样一套下来Runner 的环境变量、API 入口和任务日志都可复现后续扩容只需要增加 Runner 实例不需要改模型调用方式。如果你还没有 Key或者想先确认模型入口可以从下面四个路径进入先看 模型对话再了解 Coding Plan然后到 API Keys 创建 Key最后对照 Claude Code 文档 把 Claude Code 和 Codex 的配置分开落地。更多入口和说明见 TaoToken 官网。把 Runner 跑通之后再考虑并发、队列、审计和 Key 轮换内网 Codex 才算真正可用。
返回列表