1. 为什么 ModelArts 里的 Codex 总是登录不上
先说清楚这篇要解决什么。Codex 是 OpenAI 出的编码代理工具,既能当 VS Code 插件用,也能在终端里跑 CLI;ModelArts 是华为云的 AI 开发平台,Notebook 实例本质上是一台远程 Linux 容器,你通过 VS Code Remote-SSH 连上去写代码。把这两个东西凑一起,问题就来了:Codex 的登录链路默认要在本机浏览器里完成 OAuth 回调,而 ModelArts 容器里既没有浏览器,回调端口也回不来,于是你会看到一堆看似无关的报错——Port 127.0.0.1:1455 is already in use、403 Forbidden、EROFS: read-only file system、Could not resolve hostname,甚至登录明明成功了插件还是转圈。
这篇适合谁:正在用 VS Code 远程连 ModelArts Notebook、想在里面跑 Codex CLI 或插件的开发者;已经被 auth.json、Base URL、代理环境变量绕晕的人;以及想把「本机登录 + 远端复用凭据」这套流程固定下来的团队。核心检索词就是 Codex 登录配置、auth.json 改写、VS Code 远程 ModelArts 接入。
我踩过的坑是:一开始以为登录失败是网络问题,折腾了半天代理,最后发现根因是旧版 Codex CLI 的openai_base_url被某个自定义地址覆盖了,请求根本没发到该去的地方。所以这篇不按「先装再登」的常规顺序讲,而是按「登录链路 → 凭据落地 → 请求验证」的真实排障顺序来,每一步都给可复制的命令和配置。
整条链路可以拆成四段:本机完成 Codex 登录拿到auth.json;把凭据同步到 ModelArts 容器;在容器里把 Codex 的 Base URL 指向统一网关;最后用一次成功请求和一次 401 对照,确认配置真的生效。下面逐段展开。
2. TaoToken 前置:统一 Key 与 Base URL 怎么准备
在动手改auth.json之前,得先有一个稳定的请求出口。Codex CLI 和插件默认打的是 OpenAI 官方端点,但在 ModelArts 这种受限网络环境里,直连经常不稳定,而且多环境(本机、容器、CI)各配一套 Key 很难管理。TaoToken 在这里的角色就是一个统一的 API 网关:你拿一个 Key,配一个 Base URL,本机和远端都用同一套,省得每个环境单独折腾。
先注册并拿到 Key。打开官网 https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,完成账号注册后进入控制台。控制台地址是 https://taotoken.net/console?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,在里面可以创建 API Key。Key 的创建入口在 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,点新建,复制出来的一串就是后面要填进配置的凭据。注意 Key 只在创建时完整显示一次,先存到密码管理器里。
Base URL 统一用https://taotoken.net/api,这个地址不加任何查询参数,直接作为 OpenAI 兼容端点使用。也就是说,凡是支持自定义base_url的工具,填这个就行。Codex CLI 读的是~/.codex/config.toml里的openai_base_url,VS Code 插件则走它自己的设置项,两边指向同一个地址。
模型 ID 这块要留意:Codex 场景下常用的模型标识需要和你账号里可用的模型对齐,填错会直接报模型不存在。你可以在模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 先手动发一条消息,确认当前 Key 能正常调用、返回正常,再去配 CLI。这一步能帮你把「Key 无效」和「配置写错」两类问题提前分开。
如果你打算长期在 ModelArts 里跑编码代理、做多轮 Agent 任务,可以考虑 Coding Plan,入口在 https://taotoken.net/coding-plan?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,它更适合高频调用场景。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,遇到参数细节可以对照查。
这里要强调一个原则:TaoToken 是请求出口,不是编辑器替代品,也不是让你绕过什么限制。它的价值在于把多环境的凭据收敛成一套,让本机登录、容器复用、插件调用走同一条链路,排障时只需要盯一个 Base URL 和一个 Key。
3. 可复制配置:auth.json 与 config.toml 落地
这一节是全文的核心,所有片段都可以直接复制。先明确两个文件的职责:~/.codex/auth.json存的是登录凭据(token 之类),~/.codex/config.toml存的是行为配置(Base URL、模型、审批策略)。很多人登录失败,是因为只改了其中一个,或者两个文件里的地址不一致。
先看config.toml。在 ModelArts 容器里执行:
mkdir -p ~/.codex cat > ~/.codex/config.toml <<'EOF' model = "gpt-5-codex" openai_base_url = "https://taotoken.net/api" [model_providers.taotoken] name = "TaoToken" base_url = "https://taotoken.net/api" wire_api = "responses" [profiles.default] model_provider = "taotoken" approval_policy = "on-request" EOF这里openai_base_url是关键,它决定了请求发往哪里。之前那个「请求被发到https://api.mczbc.cn/v1/responses」的问题,就是某个环境变量或旧配置覆盖了这个字段。所以写完一定要回头确认文件里没有残留的自定义地址。
再看auth.json。它的结构大致如下,OPENAI_API_KEY字段填你在控制台创建的 Key:
{ "OPENAI_API_KEY": "sk-你的TaoToken密钥", "tokens": { "access_token": "", "refresh_token": "" }, "last_refresh": "2025-01-01T00:00:00Z" }如果你是在本机已经用codex login登录成功、想把凭据复用到远端,那就不要手写这个文件,而是直接复制本机生成的auth.json。本机路径在 Windows 下是C:\Users\你的用户名\.codex\auth.json,复制命令:
scp -F C:\Users\你的用户名\.ssh\config-modelarts ^ %USERPROFILE%\.codex\auth.json ^ ModelArts-notebook:~/.codex/auth.json注意-F参数指定了 SSH 配置文件,否则 PowerShell 里的scp只会读默认的config,就会出现Could not resolve hostname。远端目录要先建好:
ssh -F C:\Users\你的用户名\.ssh\config-modelarts ModelArts-notebook "mkdir -p ~/.codex"VS Code 插件这边,如果你用的是 Remote-SSH 连 ModelArts,插件设置里同样要填 Base URL 和 Key。打开设置搜索codex,把 API Base 填成https://taotoken.net/api,Key 填同一个。插件和 CLI 共用一套凭据时,最省事的做法就是让插件读~/.codex/auth.json,避免两处 Key 不一致。
还有一个容易忽略的点:ModelArts 容器的全局 npm 目录是只读的,npm install -g @openai/codex会报EROFS: read-only file system。改成装到用户目录:
mkdir -p ~/.local/codex npm install -g @openai/codex --prefix ~/.local/codex export PATH="$HOME/.local/codex/bin:$PATH" codex --version要让 PATH 永久生效,追加到~/.bashrc:
echo 'export PATH="$HOME/.local/codex/bin:$PATH"' >> ~/.bashrc source ~/.bashrc到这里,三件套就齐了:Base URL 是https://taotoken.net/api,Key 是控制台创建的那串,Model ID 是gpt-5-codex(按你账号实际可用的填)。三者缺一,请求都会失败。
4. 验证请求:一次成功与一次 401 对照
配置写完不能只看文件,得用真实请求验证。先做一次正向验证,确认链路通。在 ModelArts 容器里执行:
codex exec "print hello" --model gpt-5-codex如果配置正确,你会看到 Codex 正常返回内容,终端里没有报错。这一步成功说明:Base URL 可达、Key 有效、模型 ID 正确、auth.json被正确读取。
再做一次反向对照,故意把 Key 改错,观察报错长什么样。把auth.json里的OPENAI_API_KEY临时改成sk-invalid,再跑一次同样的命令,你会看到类似:
401 Unauthorized {"error":{"message":"Invalid API key provided","type":"invalid_request_error"}}这个 401 就是「Key 无效」的标准形态。记住它的样子,以后遇到 401 就不用怀疑网络,直接查 Key。反过来,如果你看到的是local proxy failed或连接超时,那才是网络层问题,要去查代理环境变量。
还有一种报错是reading choices相关的解析失败,通常出现在响应格式和预期不符时,多半是 Base URL 指错了端点,或者wire_api配成了不匹配的值。这时候回到config.toml确认wire_api = "responses"和base_url是否一致。
验证通过后,建议把这次成功的命令和输出记下来,作为基线。以后环境变动(换实例、重装、改配置)后,先跑这条基线命令,能快速判断是环境问题还是配置问题。
如果你更习惯图形化验证,可以打开模型对话页面 https://taotoken.net/chat?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= ,用同一个 Key 发一条消息。网页能通、CLI 不通,问题就在 CLI 配置;两边都不通,问题在 Key 或账号。这个二分法能省很多时间。
5. 常见报错排查:401、proxy failed、OAuth 逐个拆
这一节按真实报错对照,每条都给定位思路。
401 Unauthorized / Invalid API key:Key 错了、过期了,或者auth.json没被读到。先确认文件路径是~/.codex/auth.json,权限是当前用户可读。再确认 Key 没有多余空格或换行。如果本机登录成功、远端复制后 401,检查复制时有没有把文件内容截断。
local proxy failed / connection refused:请求根本没出去。ModelArts 容器默认会带HTTP_PROXY=http://proxy-notebook.modelarts.com:8083这类环境变量,它会覆盖你的设置。先看当前环境:
env | grep -i proxy如果显示的是平台自带代理,而你想走自己的链路,需要显式切换:
unset http_proxy https_proxy HTTP_PROXY HTTPS_PROXY ALL_PROXY all_proxy export HTTPS_PROXY=http://127.0.0.1:10240 export HTTP_PROXY=http://127.0.0.1:10240注意 VS Code 设置里的Http: Proxy只作用于 VS Code 自身的网络请求,不会自动覆盖远端终端里的curl、npm、codex。这是很多人以为「设了代理却没生效」的原因。
OAuth 回调失败 / Port 1455 already in use:本机codex login默认起一个本地回调端口,被占用就登不上。改用设备码登录:
codex logout codex login --device-auth设备码登录不依赖本地端口,适合容器和远程场景。如果远端执行codex login --device-auth返回 403,说明远端这条登录路径不可用,那就回到「本机登录 + 复制 auth.json」的方案。
EROFS: read-only file system:前面提过,全局 npm 目录只读,改用--prefix ~/.local/codex装到用户目录。
Could not resolve hostname:ssh/scp没读到你的自定义 SSH 配置。加-F指定配置文件路径,或者把 Host 写进默认config。
codex: command not found:~/.codex目录存在不代表 CLI 装好了。~/.codex是配置目录,可执行文件在~/.local/codex/bin/codex。用find ~/.local -name codex确认位置,再把 bin 目录加进 PATH。
排查时有个通用顺序:先看报错类型(401 是凭据,proxy failed 是网络,EROFS 是权限),再定位到对应文件或环境变量,最后用一条最小命令验证。不要一上来就重装,多数问题改一行配置就能解决。
6. 把配置固定下来:多环境复用与后续接入
配置能跑通只是第一步,真正省心的是把它固定成可复用的流程。我的做法是:本机保留一份登录好的auth.json作为母版,每次新建 ModelArts 实例后,用一条脚本把凭据和配置同步过去。
同步脚本大致长这样:
#!/bin/bash HOST="ModelArts-notebook" SSH_CONF="C:/Users/你的用户名/.ssh/config-modelarts" ssh -F "$SSH_CONF" "$HOST" "mkdir -p ~/.codex ~/.local/codex" scp -F "$SSH_CONF" ~/.codex/auth.json "$HOST:~/.codex/auth.json" scp -F "$SSH_CONF" ~/.codex/config.toml "$HOST:~/.codex/config.toml" ssh -F "$SSH_CONF" "$HOST" "grep -q '.local/codex/bin' ~/.bashrc || echo 'export PATH=\"\$HOME/.local/codex/bin:\$PATH\"' >> ~/.bashrc"这样每次换实例,跑一遍脚本,Codex 就能直接用。Key 轮换时也只需要更新本机母版,再同步一次。
VS Code 这边,如果你同时用新版和旧版(比如旧版专门连 ModelArts 以兼容老系统的 libstdc++),记得给旧版单独指定 SSH 配置文件,避免两个实例互相覆盖:
{ "remote.SSH.configFile": "C:\\Users\\你的用户名\\.ssh\\config-modelarts" }新版继续用默认config,两边互不干扰。
后续如果你要接更多工具,比如 Cline、Codex 的 MCP 配置,或者 Claude Code 这类同样支持自定义端点的工具,思路是一样的:Base URL 填https://taotoken.net/api,Key 用同一个,Model ID 按工具要求填。接入文档在 https://taotoken.net/doc?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 有各工具的配置示例,遇到字段不确定就对照查。需要新建或轮换 Key 时,回到 https://taotoken.net/api-keys?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content= 操作。
最后留一个实用习惯:每次改完配置,先跑codex exec "print hello"这条最小命令,通过了再干正事。它能在几秒内告诉你凭据、网络、模型三件事是否都正常,比等到写代码写到一半报错再回头查要高效得多。