文章

CodexPro + Cloudflare Named Tunnel:固定域名配置与排障

CodexPro + Cloudflare Named Tunnel:固定域名配置与排障

本文记录如何为 CodexPro 配置 Cloudflare Named Tunnel,通过固定 HTTPS 子域名公开本地 MCP 服务,并覆盖登录卡住、DNS 冲突、Tunnel Down、502、代理干扰和 ChatGPT 无法连接等常见问题。

本文假设域名已接入 Cloudflare,且本地 CodexPro 服务监听 127.0.0.1:8787

示例参数

本文中的域名、用户名、项目名和路径均为通用示例。实际操作时请统一替换为自己的配置。

配置项 示例值
Linux 用户名 example-user
项目名称 example-project
项目目录 /home/example-user/Code/example-project
根域名 example.com
CodexPro 子域名 codexpro.example.com
Tunnel 名称 codexpro-example-project
本地服务 http://127.0.0.1:8787
MCP 地址 http://127.0.0.1:8787/mcp

example.com 是文档专用示例域名,不应直接用于真实部署。


1. 更新并检查 CodexPro

进入项目目录:

1
cd /home/example-user/Code/example-project

检查当前版本:

1
2
3
node --version
codexpro --version
codexpro --help

更新 CodexPro:

1
npm install -g codexpro@latest

检查 stable 命令:

1
codexpro stable --help

确认支持以下参数:

1
2
3
4
5
6
--root
--hostname
--tunnel-name
--token
--mode
--bash

2. 安装 cloudflared

优先使用 CodexPro 自带安装命令:

1
codexpro install-cloudflared

检查版本:

1
~/.codexpro/bin/cloudflared --version

默认安装位置:

1
~/.codexpro/bin/cloudflared

如果找不到 install-cloudflared

1
2
npm install -g codexpro@latest
codexpro install-cloudflared

3. 登录 Cloudflare Tunnel

执行:

1
~/.codexpro/bin/cloudflared tunnel login

终端会输出授权 URL:

1
2
3
A browser window should have opened at the following URL:
https://dash.cloudflare.com/argotunnel?...
Waiting for login...

操作步骤:

  1. 保持终端中的命令继续运行。
  2. 在浏览器打开终端输出的完整 URL。
  3. 登录当前 Cloudflare 账号。
  4. 选择域名 example.com
  5. 点击授权。
  6. 等待浏览器明确显示授权成功。
  7. 返回 Ubuntu 终端。

成功后检查:

1
ls -la ~/.cloudflared/

应存在:

1
cert.pem

登录后仍显示 Waiting for login...

先检查是否生成证书:

1
ls -l ~/.cloudflared/cert.pem

如果证书不存在,终止旧进程并重试:

1
2
3
pkill -f cloudflared || true

~/.codexpro/bin/cloudflared tunnel login

注意:只登录 Cloudflare 账号不够,必须继续完成:

1
2
3
选择 example.com
→ 点击授权
→ 浏览器显示授权成功

检查代理环境:

1
env | grep -i proxy

临时取消终端代理后重试:

1
2
3
4
5
6
7
8
unset http_proxy
unset https_proxy
unset HTTP_PROXY
unset HTTPS_PROXY
unset all_proxy
unset ALL_PROXY

~/.codexpro/bin/cloudflared tunnel login

如果使用 Clash,建议分别测试:

1
2
3
1. 关闭 Clash 虚拟网卡后登录
2. 保留 Clash,但清除终端代理变量后登录
3. 确认 cloudflared 没有被代理规则阻断

4. 创建 Named Tunnel

4.1 创建 Tunnel

1
~/.codexpro/bin/cloudflared tunnel create codexpro-example-project

成功后会生成凭据文件:

1
~/.cloudflared/<TUNNEL-UUID>.json

查看 Tunnel:

1
~/.codexpro/bin/cloudflared tunnel list

应看到:

1
codexpro-example-project

4.2 绑定固定子域名

1
2
3
~/.codexpro/bin/cloudflared tunnel route dns \
  codexpro-example-project \
  codexpro.example.com

该命令会在 Cloudflare DNS 中创建类似记录:

1
2
3
4
类型:CNAME
名称:codexpro
目标:<TUNNEL-UUID>.cfargotunnel.com
代理:开启

在 Cloudflare 控制台检查:

1
2
3
example.com
→ DNS
→ Records

应看到:

1
2
3
4
CNAME
codexpro
<TUNNEL-UUID>.cfargotunnel.com
Proxied

不要额外创建以下记录:

1
2
3
A codexpro → 127.0.0.1
A codexpro → 192.168.x.x
A codexpro → 本地公网 IP

4.3 DNS 记录冲突

如果执行 route dns 时提示记录已存在:

  1. 打开 Cloudflare。
  2. 进入 example.com → DNS → Records
  3. 删除已有的 codexpro 同名记录。
  4. 重新执行:
1
2
3
~/.codexpro/bin/cloudflared tunnel route dns \
  codexpro-example-project \
  codexpro.example.com

5. 创建 CodexPro 安全 Token

创建安全目录:

1
2
mkdir -p ~/.codexpro
chmod 700 ~/.codexpro

生成随机 Token:

1
2
openssl rand -hex 32 > ~/.codexpro/codexpro-mcp-token
chmod 600 ~/.codexpro/codexpro-mcp-token

检查文件权限:

1
ls -l ~/.codexpro/codexpro-mcp-token

预期权限类似:

1
-rw------- 

不要把 Token:

  • 提交到 Git;
  • 写入项目目录;
  • 发送到公开聊天;
  • 放入截图;
  • 写死在公开脚本中。

6. 启动 CodexPro

进入项目目录:

1
cd /home/example-user/Code/example-project

执行:

1
2
3
4
5
6
7
codexpro stable \
  --root /home/example-user/Code/example-project \
  --hostname codexpro.example.com \
  --tunnel-name codexpro-example-project \
  --token "$(tr -d '\r\n' < ~/.codexpro/codexpro-mcp-token)" \
  --mode handoff \
  --bash safe

推荐保留:

1
2
--mode handoff
--bash safe

启动后应显示类似:

1
2
3
Workspace    /home/example-user/Code/example-project
Local URL    http://127.0.0.1:8787/mcp
Tunnel       codexpro.example.com

7. 验证 Tunnel

另开一个终端进行验证。

7.1 检查本地服务

1
curl -i http://127.0.0.1:8787/healthz

检查端口:

1
ss -lntp | grep 8787

7.2 检查公网服务

1
curl -i https://codexpro.example.com/healthz

7.3 检查 DNS

1
dig codexpro.example.com

也可以:

1
2
dig @1.1.1.1 codexpro.example.com
dig @8.8.8.8 codexpro.example.com

7.4 检查 Tunnel

1
~/.codexpro/bin/cloudflared tunnel list
1
~/.codexpro/bin/cloudflared tunnel info codexpro-example-project

Cloudflare 控制台中检查:

1
2
3
4
Zero Trust
→ Networks / Networking
→ Tunnels
→ codexpro-example-project

运行状态应为:

1
Healthy

8. 生成 ChatGPT Server URL

执行:

1
2
printf 'https://codexpro.example.com/mcp?codexpro_token=%s\n' \
  "$(tr -d '\r\n' < ~/.codexpro/codexpro-mcp-token)"

生成结果:

1
https://codexpro.example.com/mcp?codexpro_token=<你的Token>

将完整地址填写到 ChatGPT CodexPro 连接配置中。

关键要求:

1
2
3
路径必须包含:/mcp
查询参数必须包含:codexpro_token
Authentication:None / No Authentication

该 URL 包含私密 Token,不要公开。


9. 创建日常启动脚本

创建脚本目录:

1
mkdir -p ~/bin

创建脚本:

1
nano ~/bin/start-codexpro.sh

写入:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/env bash

set -euo pipefail

readonly REPO_ROOT="/home/example-user/Code/example-project"
readonly PUBLIC_HOST="codexpro.example.com"
readonly TUNNEL_NAME="codexpro-example-project"
readonly TOKEN_FILE="${HOME}/.codexpro/codexpro-mcp-token"

if ! command -v codexpro >/dev/null 2>&1; then
    echo "错误:未找到 codexpro,请检查安装和 PATH。" >&2
    exit 1
fi

if [[ ! -d "${REPO_ROOT}" ]]; then
    echo "错误:项目目录不存在:${REPO_ROOT}" >&2
    exit 1
fi

if [[ ! -r "${TOKEN_FILE}" ]]; then
    echo "错误:Token 文件不存在或不可读:${TOKEN_FILE}" >&2
    exit 1
fi

CODEXPRO_TOKEN="$(tr -d '\r\n' < "${TOKEN_FILE}")"

if [[ -z "${CODEXPRO_TOKEN}" ]]; then
    echo "错误:Token 文件为空:${TOKEN_FILE}" >&2
    exit 1
fi

cd "${REPO_ROOT}"

exec codexpro stable \
    --root "${REPO_ROOT}" \
    --hostname "${PUBLIC_HOST}" \
    --tunnel-name "${TUNNEL_NAME}" \
    --token "${CODEXPRO_TOKEN}" \
    --mode handoff \
    --bash safe

保存后添加执行权限:

1
chmod 700 ~/bin/start-codexpro.sh

日常启动:

1
~/bin/start-codexpro.sh

10. 常见问题排查

10.1 tunnel login 一直等待

检查证书:

1
ls -la ~/.cloudflared/cert.pem

如果不存在:

1
2
3
4
5
6
7
8
9
10
pkill -f cloudflared || true

unset http_proxy
unset https_proxy
unset HTTP_PROXY
unset HTTPS_PROXY
unset all_proxy
unset ALL_PROXY

~/.codexpro/bin/cloudflared tunnel login

浏览器必须完成:

1
2
3
4
登录
→ 选择 example.com
→ 授权
→ 显示成功

10.2 Tunnel 显示 Down

检查 Tunnel:

1
~/.codexpro/bin/cloudflared tunnel list

检查认证文件:

1
ls -la ~/.cloudflared/

检查网络:

1
curl -I https://api.cloudflare.com

检查 Cloudflare 域名是否已经为 Active:

1
dig NS example.com +short

预期返回:

1
2
<assigned-nameserver-1>.ns.cloudflare.com.
<assigned-nameserver-2>.ns.cloudflare.com.

10.3 公网返回 502

通常表示:

1
2
Cloudflare Tunnel 正常
但本地 CodexPro 没有运行

检查:

1
2
ss -lntp | grep 8787
curl -i http://127.0.0.1:8787/healthz

重新启动:

1
~/bin/start-codexpro.sh

10.4 域名无法解析

检查根域名 Nameserver:

1
dig NS example.com +short

检查子域名:

1
dig codexpro.example.com

检查 Cloudflare DNS 中是否存在:

1
2
3
CNAME
codexpro
<UUID>.cfargotunnel.com

10.5 route dns 提示记录冲突

进入:

1
2
3
4
Cloudflare
→ example.com
→ DNS
→ Records

删除已有的:

1
codexpro.example.com

重新执行:

1
2
3
~/.codexpro/bin/cloudflared tunnel route dns \
  codexpro-example-project \
  codexpro.example.com

10.6 ChatGPT 无法连接

按顺序检查:

1
2
curl -i http://127.0.0.1:8787/healthz
curl -i https://codexpro.example.com/healthz

重新生成 Server URL:

1
2
printf 'https://codexpro.example.com/mcp?codexpro_token=%s\n' \
  "$(tr -d '\r\n' < ~/.codexpro/codexpro-mcp-token)"

确认:

1
2
3
4
5
6
7
8
包含 https://
包含 codexpro.example.com
包含 /mcp
包含 codexpro_token
Token 无空格和换行
CodexPro 进程仍在运行
Tunnel 状态为 Healthy
Authentication 设置为 None

不要给 codexpro.example.com 配置需要浏览器交互登录的 Cloudflare Access 页面。

10.7 Clash 导致连接异常

检查代理变量:

1
env | grep -i proxy

临时清除:

1
2
3
4
5
6
unset http_proxy
unset https_proxy
unset HTTP_PROXY
unset HTTPS_PROXY
unset all_proxy
unset ALL_PROXY

然后重试:

1
~/.codexpro/bin/cloudflared tunnel login

或:

1
~/bin/start-codexpro.sh

10.8 一次性检查全部状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
echo "===== CodexPro Version ====="
codexpro --version

echo
echo "===== cloudflared Version ====="
~/.codexpro/bin/cloudflared --version

echo
echo "===== Cloudflare Certificate ====="
ls -la ~/.cloudflared/cert.pem

echo
echo "===== Tunnel List ====="
~/.codexpro/bin/cloudflared tunnel list

echo
echo "===== DNS Nameservers ====="
dig NS example.com +short

echo
echo "===== CodexPro DNS ====="
dig codexpro.example.com

echo
echo "===== Local Port ====="
ss -lntp | grep 8787 || true

echo
echo "===== Local Health ====="
curl -i --max-time 10 http://127.0.0.1:8787/healthz || true

echo
echo "===== Public Health ====="
curl -i --max-time 15 https://codexpro.example.com/healthz || true

11. 最终执行顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
1. 更新 CodexPro
2. 安装 cloudflared
3. 登录 Cloudflare Tunnel
4. 确认生成 cert.pem
5. 创建 codexpro-example-project Tunnel
6. 绑定 codexpro.example.com
7. 生成 CodexPro Token
8. 启动 codexpro stable
9. 验证本地 healthz
10. 验证公网 healthz
11. 生成 ChatGPT Server URL
12. 配置 ChatGPT CodexPro 连接
13. 创建日常启动脚本

核心命令汇总

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 登录 Cloudflare
~/.codexpro/bin/cloudflared tunnel login

# 创建 Tunnel
~/.codexpro/bin/cloudflared tunnel create codexpro-example-project

# 绑定域名
~/.codexpro/bin/cloudflared tunnel route dns \
  codexpro-example-project \
  codexpro.example.com

# 生成 Token
openssl rand -hex 32 > ~/.codexpro/codexpro-mcp-token
chmod 600 ~/.codexpro/codexpro-mcp-token

# 启动 CodexPro
codexpro stable \
  --root /home/example-user/Code/example-project \
  --hostname codexpro.example.com \
  --tunnel-name codexpro-example-project \
  --token "$(tr -d '\r\n' < ~/.codexpro/codexpro-mcp-token)" \
  --mode handoff \
  --bash safe
本文由作者按照 CC BY 4.0 进行授权