---
title: "在 CI/CD 中维护认证"
description: "基于官方 Codex CI/CD 认证教程，讲清 API key 默认路线、ChatGPT-managed auth 高级路线和 auth.json 的安全边界。"
verifiedAt: "2026-05-06"
---

import { Cards, Card } from 'fumadocs-ui/components/card';

Codex 自动化认证的默认答案是 API key。只有当你确实需要让 workflow 以你的 Codex account 身份运行时，才使用 ChatGPT-managed auth 的高级方案。

> [!CAUTION]
> `~/.codex/auth.json` 包含 access tokens，按密码处理。不要 commit、贴工单、发聊天、进日志、进 artifact，也不要用于 public 或 open-source repository。

<Cards>
  <Card title="CI/CD auth" href="https://developers.openai.com/codex/auth/ci-cd-auth">
    官方高级 `auth.json` 维护方案。
  </Card>
  <Card title="Non-interactive mode" href="/docs/codex/official/01-products/28-non-interactive">
    大多数 CI 任务直接用 API key 跑 `codex exec`。
  </Card>
  <Card title="GitHub Action" href="/docs/codex/official/06-team-integration/45-github-action">
    GitHub Actions 场景优先走官方 action 和 secret。
  </Card>
</Cards>

## 两条路线

```mermaid
flowchart LR
    CI["CI/CD job"] --> API["API key secret"]
    CI --> Auth["ChatGPT-managed auth.json"]
    API --> Default["default route"]
    Auth --> Advanced["trusted private runner only"]
```

API key 路线：把 `CODEX_API_KEY` 或 action 需要的 OpenAI key 放进 CI secret，由 job 注入。它更容易发放、轮换和撤销，是大多数自动化默认选择。

ChatGPT-managed auth 路线：先在可信机器上 `codex login` 生成 `auth.json`，把它放到可信 runner，让 Codex 在运行中使用内置 refresh flow，并把更新后的 `auth.json` 留给下一次 run。

第二条路线的核心不是“自己调用 refresh API”。官方推荐的是运行 Codex，让 Codex 自己刷新，然后持久化刷新后的文件。

## 怎么选择

用 API key：

- 普通 CI/CD。
- 公开仓库或开源仓库。
- GitHub Actions、GitLab CI、Jenkins 等常规自动化。
- 只需要跑 `codex exec` 或 Codex GitHub Action。
- 希望凭据容易轮换。

考虑 ChatGPT-managed auth：

- 必须以 Codex account 身份运行，而不是 API key。
- runner 是可信私有基础设施。
- 远程 runner 不能运行 browser login。
- 能在 runs 之间保存刷新后的 `auth.json`。
- 同一份 `auth.json` 不会被并发 job 或多台机器同时使用。

有一项不满足，就不要用 `auth.json` 方案。

## auth.json 风险

`auth.json` 不适合多机共享。一个 runner 或一个串行 workflow stream 使用一份独立 copy。并发使用会导致 token refresh 互相覆盖，最终出现 401 或无法刷新。

Self-hosted runner 最适合高级方案，因为它能在 jobs 之间保留 `CODEX_HOME`。第一次缺文件时 seed `auth.json`，后续不要每次用原始 secret 覆盖它。

Ephemeral runner 也能做，但必须实现 restore、run、persist 闭环：

1. 从安全存储恢复当前 `auth.json`。
2. 运行 Codex。
3. 把本次可能刷新过的文件写回安全存储。

关键点是写回刷新后的文件，不是写回原始 seed。

## 常见坑

- 在公开仓库里用 ChatGPT-managed auth。
- 把 `auth.json` 当普通配置文件。
- 每次 run 都覆盖原文件，丢掉刷新后的 token。
- 多个并发 job 共享同一份 `auth.json`。
- 自己手写 OAuth refresh 请求。
- refresh token 被 revoke、expired 或被别的机器旋转后，没有重新 seed。
- 把完整 `auth.json` 上传 artifact。

## 出问题怎么判断

出现 401 时，先判断：

- runner 是否能读取当前 `auth.json`。
- 它是否被旧 secret 覆盖。
- 是否有并发 job 使用同一份文件。
- secure storage 的 restore / persist 是否成功。
- persist 是否写回本次运行后的文件。

仍然失败时，不要手写 refresh 请求。回到可信机器重新 `codex login`，生成新的 `auth.json`，重新 seed runner。

## 验收清单

- API key 只存在 CI secret 中，日志没有打印。
- job 能运行 `codex exec`，失败时能轮换 key。
- ChatGPT-managed auth 只在可信私有 runner 使用。
- `auth.json` 权限收紧，没有进入仓库、日志和 artifact。
- 每次 run 后能保留刷新后的文件。
- 同一份 `auth.json` 不会被两个 job 同时使用。
- 一旦怀疑泄露，立即重新登录、替换 secret、撤销旧凭据。

## 官方资料

- [Maintain Codex account auth in CI/CD](https://developers.openai.com/codex/auth/ci-cd-auth)
- [Non-interactive mode](https://developers.openai.com/codex/noninteractive)
- [Codex GitHub Action](https://developers.openai.com/codex/github-action)
