0%

服务器 Codex 反向代理使用说明

服务器 Codex 反向代理使用说明

1. 使用场景

服务器无法直接访问外网,但本地 Windows 电脑可以通过 v2rayN、Clash 等代理访问外网。

目标链路如下:

1
2
3
4
5
6
7
服务器上的 Codex

服务器 127.0.0.1:代理端口
↓ SSH 反向隧道
本地电脑 127.0.0.1:7897

外网

该配置只在当前用户账户下生效,不修改服务器全局代理,不影响其他 Linux 用户。

2. 前提条件

2.1 本地电脑

本地电脑需要已经有可用代理,例如:

1
127.0.0.1:7897

可在 Windows PowerShell 中测试:

1
curl.exe -I -x http://127.0.0.1:7897 https://www.google.com

如果返回 HTTP/2 200 或类似结果,说明本地代理可用。

2.2 服务器

服务器需要能够通过 SSH 登录:

1
ssh your_user@your_server_ip

3. 在本地电脑建立 SSH 反向代理

在 Windows PowerShell 中执行:

1
ssh -N -T -o ExitOnForwardFailure=yes -R 43897:127.0.0.1:7897 your_user@your_server_ip

参数说明:

1
2
3
4
5
6
-N:只建立隧道,不进入远程 shell
-T:不分配伪终端
-o ExitOnForwardFailure=yes:如果端口转发失败则直接退出
-R 43897:127.0.0.1:7897:
在服务器上监听 127.0.0.1:43897
并转发到本地电脑的 127.0.0.1:7897

执行后窗口看起来会停住,这是正常现象。该窗口用于保持 SSH 隧道连接,不要关闭。

如需中断隧道,在该 PowerShell 窗口按:

1
Ctrl + C

4. 在服务器上测试代理是否可用

另开一个 PowerShell 窗口,登录服务器:

1
ssh your_user@your_server_ip

在服务器中执行:

1
curl -I -x http://127.0.0.1:43897 https://www.google.com

如果出现类似结果:

1
2
3
HTTP/1.1 200 Connection established

HTTP/2 200

说明反向代理已经成功。

也可以测试 OpenAI:

1
curl -I -x http://127.0.0.1:43897 https://api.openai.com

5. 检查服务器端监听端口

在服务器上执行:

1
ss -lntp | grep 43897

正常情况下应看到类似:

1
LISTEN 0 128 127.0.0.1:43897 0.0.0.0:*

重点是监听地址应为:

1
127.0.0.1:43897

不要是:

1
0.0.0.0:43897

127.0.0.1 表示该端口只在服务器本机可访问,不暴露给外部网络。

注意:同一台服务器上的其他 Linux 用户理论上也可能访问 127.0.0.1:43897。因此建议使用随机高位端口,并且不要公开端口号。

6. 安装 Node.js 和 npm

先检查服务器是否已有 Node.js 和 npm:

1
2
node -v
npm -v

如果能正常显示版本号,可以跳过本节。

如果没有 Node.js,且没有 sudo 权限,建议使用 nvm 安装到当前用户目录。

通过代理安装 nvm:

1
2
3
HTTPS_PROXY=http://127.0.0.1:43897 \
HTTP_PROXY=http://127.0.0.1:43897 \
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash

加载 nvm:

1
source ~/.bashrc

安装 Node.js LTS:

1
2
nvm install --lts
nvm use --lts

再次检查:

1
2
node -v
npm -v

7. 配置 npm 只安装到当前用户目录

不要使用系统级全局安装路径,避免影响服务器其他用户。

在服务器中执行:

1
2
mkdir -p ~/.npm-global
npm config set prefix "$HOME/.npm-global"

将当前用户的 npm bin 目录加入 PATH:

1
2
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

检查 npm 全局安装目录:

1
npm config get prefix

期望输出类似:

1
/home/your_user/.npm-global

8. 通过代理安装 Codex CLI

在服务器中执行:

1
2
3
4
HTTPS_PROXY=http://127.0.0.1:43897 \
HTTP_PROXY=http://127.0.0.1:43897 \
ALL_PROXY=http://127.0.0.1:43897 \
npm install -g @openai/codex

安装完成后检查:

1
2
which codex
codex --version

期望结果类似:

1
/home/your_user/.npm-global/bin/codex

如果 which codex 指向 /home/your_user/.npm-global/bin/codex,说明 Codex 安装在当前用户目录下,不影响其他用户。

9. 创建只对 Codex 生效的代理启动脚本

不要把代理变量直接写入 ~/.bashrc,否则当前账户下的其他程序也会默认走代理。

推荐创建单独脚本。注意同时设置大写和小写代理变量,因为 Codex 及其子进程可能读取不同大小写的环境变量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
mkdir -p ~/bin
cat > ~/bin/codex-proxy <<'EOF'
#!/usr/bin/env bash
set -e

export HTTP_PROXY=http://127.0.0.1:43897
export HTTPS_PROXY=http://127.0.0.1:43897
export ALL_PROXY=http://127.0.0.1:43897
export NO_PROXY=localhost,127.0.0.1,::1

export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"

exec "$HOME/.npm-global/bin/codex" "$@"
EOF

赋予执行权限:

1
chmod +x ~/bin/codex-proxy

~/bin 加入当前用户 PATH:

1
2
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

检查:

1
which codex-proxy

期望结果:

1
/home/your_user/bin/codex-proxy

9.1 给 Codex app-server 添加代理包装

Codex 可能会自动拉起 codex app-servercodex app-server proxy 子进程。实际使用中,这些子进程不一定继承当前终端手动 export 的代理变量,并且自动启动命令会优先从:

1
~/.local/bin/codex

查找 codex。因此建议额外放一个同样的包装脚本到 ~/.local/bin/codex,让自动拉起的 app-server 也走代理。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mkdir -p ~/.local/bin
cat > ~/.local/bin/codex <<'EOF'
#!/usr/bin/env bash
set -e

export HTTP_PROXY=http://127.0.0.1:43897
export HTTPS_PROXY=http://127.0.0.1:43897
export ALL_PROXY=http://127.0.0.1:43897
export NO_PROXY=localhost,127.0.0.1,::1

export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"

exec "$HOME/.npm-global/bin/codex" "$@"
EOF

chmod +x ~/.local/bin/codex

创建后检查:

1
2
~/.local/bin/codex --version
codex-proxy --version

10. 登录 Codex

使用代理脚本启动登录:

1
codex-proxy login

如果支持设备码登录,也可以使用:

1
codex-proxy login --device-auth

服务器无浏览器时,终端一般会显示登录链接或设备码。将链接复制到本地浏览器完成登录即可。

11. 启动 Codex

进入项目目录:

1
cd /path/to/project

启动 Codex:

1
codex-proxy

不要直接运行:

1
codex

因为直接运行 codex 不会自动带上代理环境变量。

12. Docker 容器内使用 Codex

如果 Codex 或开发环境在 Docker 容器内,不要修改 Docker daemon 全局代理。

建议只给自己的容器传入代理变量。

启动容器时:

1
2
3
4
5
6
docker run -it \
--add-host=host.docker.internal:host-gateway \
-e HTTP_PROXY=http://host.docker.internal:43897 \
-e HTTPS_PROXY=http://host.docker.internal:43897 \
-e ALL_PROXY=http://host.docker.internal:43897 \
your_image bash

如果使用 docker compose,只在自己的服务中添加:

1
2
3
4
5
6
7
8
9
services:
dev:
image: your_image
extra_hosts:
- "host.docker.internal:host-gateway"
environment:
HTTP_PROXY: http://host.docker.internal:43897
HTTPS_PROXY: http://host.docker.internal:43897
ALL_PROXY: http://host.docker.internal:43897

不要修改:

1
/etc/docker/daemon.json

否则可能影响服务器其他用户的 Docker 网络行为。

13. 多用户服务器注意事项

13.1 Codex 程序隔离

如果 Codex 安装在:

1
/home/your_user/.npm-global/bin/codex

并且只将路径写入:

1
/home/your_user/.bashrc

则其他用户默认无法直接通过 codex 命令访问你的 Codex。

检查方式:

1
2
which codex
ls -l $(which codex)

期望结果:

1
/home/your_user/.npm-global/bin/codex

13.2 代理端口风险

SSH 反向代理监听在服务器本机:

1
127.0.0.1:43897

外部机器不能直接访问,但同一台服务器上的其他用户理论上可能访问该本机端口。

降低风险的方法:

  1. 使用随机高位端口,例如 5917347281 等。
  2. 不要将代理端口写入公共文档或共享脚本。
  3. 不要将代理环境变量写入全局配置。
  4. 只在 ~/bin/codex-proxy 中使用代理。
  5. 使用完后关闭 SSH 隧道。

例如将端口换为 59173

本地电脑执行:

1
ssh -N -T -o ExitOnForwardFailure=yes -R 59173:127.0.0.1:7897 your_user@your_server_ip

服务器脚本中对应修改为:

1
2
3
export HTTP_PROXY=http://127.0.0.1:59173
export HTTPS_PROXY=http://127.0.0.1:59173
export ALL_PROXY=http://127.0.0.1:59173

14. 权限加固

如果不希望其他用户浏览你的用户目录,可执行:

1
2
chmod 700 ~
chmod 700 ~/.npm-global ~/bin

检查权限:

1
2
ls -ld ~
ls -ld ~/.npm-global ~/bin

15. 常见问题

15.1 PowerShell 执行 SSH 后卡住

正常。

如果使用了:

1
ssh -N -R 43897:127.0.0.1:7897 your_user@your_server_ip

-N 表示只建立隧道,不打开远程 shell,因此不会出现服务器命令行提示符。

该窗口需要保持打开,关闭后隧道断开。

15.2 curl 测试返回 Connection refused

可能原因:

  1. 本地代理端口不是 7897
  2. 本地 v2rayN 或 Clash 没有开启。
  3. SSH 反向隧道没有成功。
  4. 服务器端口 43897 被占用。
  5. 本地代理只监听了其他地址或端口。

检查本地代理端口是否正确。

15.3 curl 测试返回 Could not resolve host

可能是代理没有生效,或者命令没有指定 -x

应使用:

1
curl -I -x http://127.0.0.1:43897 https://www.google.com

15.4 npm install 仍然无法联网

使用显式代理变量安装:

1
2
3
4
HTTPS_PROXY=http://127.0.0.1:43897 \
HTTP_PROXY=http://127.0.0.1:43897 \
ALL_PROXY=http://127.0.0.1:43897 \
npm install -g @openai/codex

必要时也可以设置 npm 代理:

1
2
npm config set proxy http://127.0.0.1:43897
npm config set https-proxy http://127.0.0.1:43897

如果后续不想让 npm 默认走代理,可以删除:

1
2
npm config delete proxy
npm config delete https-proxy

15.5 codex-proxy 提示 command not found

检查 ~/bin 是否加入 PATH:

1
echo $PATH

重新执行:

1
2
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

检查脚本是否存在:

1
ls -l ~/bin/codex-proxy

15.6 codex 命令找不到

检查 Codex 是否安装成功:

1
npm list -g --depth=0

检查 npm 全局 bin 目录:

1
npm bin -g

检查 PATH:

1
echo $PATH

确保包含:

1
/home/your_user/.npm-global/bin

15.7 Codex 主进程有代理,但 codex_apps 或 MCP 仍然失败

如果报错中出现类似:

1
2
3
4
MCP startup failed
codex_apps
https://chatgpt.com/backend-api/wham/apps
tls handshake eof

先确认代理链路本身是否可用:

1
curl -v -x http://127.0.0.1:43897 https://chatgpt.com/backend-api/wham/apps

如果能看到 HTTP/1.1 200 Connection established,并且最终返回 HTTP/2 405 或其他 HTTP 响应,说明代理链路是通的。

此时重点检查是否有旧的无代理 codex app-server 进程残留:

1
ps -u "$(whoami)" -o pid=,cmd= | grep 'codex app-server' | grep -v grep

如果存在旧进程,可以只清理当前用户下的 app-server:

1
2
3
4
5
ps -u "$(whoami)" -o pid=,cmd= \
| grep 'codex app-server' \
| grep -v grep \
| awk '{print $1}' \
| xargs -r kill -9

不要直接使用不带用户限制的 pkill -f codex,多用户服务器上可能匹配到其他人的 Codex 进程并出现无权限错误。

清理后重新运行:

1
codex-proxy

16. 日常使用流程

第一步:本地电脑打开 SSH 隧道

1
ssh -N -T -o ExitOnForwardFailure=yes -R 43897:127.0.0.1:7897 your_user@your_server_ip

保持该窗口不关闭。

第二步:另开终端登录服务器

1
ssh your_user@your_server_ip

第三步:进入项目目录

1
cd /path/to/project

第四步:启动 Codex

1
codex-proxy

第五步:使用结束后关闭隧道

回到保持隧道的 PowerShell 窗口,按:

1
Ctrl + C

17. 最小命令汇总

本地电脑

1
ssh -N -T -o ExitOnForwardFailure=yes -R 43897:127.0.0.1:7897 your_user@your_server_ip

服务器测试代理

1
curl -I -x http://127.0.0.1:43897 https://www.google.com

服务器安装 Codex

1
2
3
4
5
6
7
8
9
mkdir -p ~/.npm-global
npm config set prefix "$HOME/.npm-global"
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

HTTPS_PROXY=http://127.0.0.1:43897 \
HTTP_PROXY=http://127.0.0.1:43897 \
ALL_PROXY=http://127.0.0.1:43897 \
npm install -g @openai/codex

创建 Codex 代理启动脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
mkdir -p ~/bin
cat > ~/bin/codex-proxy <<'EOF'
#!/usr/bin/env bash
set -e

export HTTP_PROXY=http://127.0.0.1:43897
export HTTPS_PROXY=http://127.0.0.1:43897
export ALL_PROXY=http://127.0.0.1:43897
export NO_PROXY=localhost,127.0.0.1,::1

export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"

exec "$HOME/.npm-global/bin/codex" "$@"
EOF

chmod +x ~/bin/codex-proxy
echo 'export PATH="$HOME/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc

创建 Codex app-server 包装脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
mkdir -p ~/.local/bin
cat > ~/.local/bin/codex <<'EOF'
#!/usr/bin/env bash
set -e

export HTTP_PROXY=http://127.0.0.1:43897
export HTTPS_PROXY=http://127.0.0.1:43897
export ALL_PROXY=http://127.0.0.1:43897
export NO_PROXY=localhost,127.0.0.1,::1

export http_proxy="$HTTP_PROXY"
export https_proxy="$HTTPS_PROXY"
export all_proxy="$ALL_PROXY"
export no_proxy="$NO_PROXY"

exec "$HOME/.npm-global/bin/codex" "$@"
EOF

chmod +x ~/.local/bin/codex

启动 Codex

1
codex-proxy