前言

之前 在本地部署了CPA。本质上,本地部署和云端部署是一样的,我只是不想每次开电脑后再启动两个命令行界面。

我的服务器端较为复杂,前端由隧道服务端监听443端口分流到NGINX。我们的服务都是本地端口,且只有HTTP,因此还需要配置NGINX反代。钻研了一下午才搞定。

CPA & CPAM 配置

CPA

服务器端配置和本地差不多,记得端口监听地址改为127.0.0.1即可。

CPAM

CPAM有多种配置方案。具体参考CPA-Manager/README_CN.md at main · seakee/CPA-Manager

我选择的是使用systemd单文件运行的方式。实在不想重新拉Docker配置了。

同样设置监听地址为127.0.0.1

隧道服务端配置

如果隧道的域名和API地址域名一致,就不用考虑泛域名证书。否则,必须申请,因为隧道服务端不支持多个证书配置,只能选择单个域名证书或者泛域名证书。下面配置基于不同隧道域名与API域名地址,假设申请的泛域名证书是*.0d000721.xyz

首先设置fallback目标。这里任意设四个不同fallback目标,分别对应:

  • 隧道地址
  • 隧道地址h2
  • API地址
  • API地址h2

为什么要单独区分h2?因为后续开启WebSocket后会走HTTP/1.1进行Upgrade。

参考配置如下:

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
{
"settings": {
"fallbacks": [
{
"name": "tunnel.0d000721.xyz",
"dest": "127.0.0.1:8001",
"xver": 1
},
{
"name": "tunnel.0d000721.xyz",
"alpn": "h2",
"dest": "127.0.0.1:8002",
"xver": 1
},
{
"name": "api.0d000721.xyz",
"dest": "127.0.0.1:8003",
"xver": 1
},
{
"name": "api.0d000721.xyz",
"alpn": "h2",
"dest": "127.0.0.1:8004",
"xver": 1
}
]
}
}

NGINX 配置

NGINX 要同步监听上面配置写的fallback端口。隧道的配置不用管,保持即可,重点是配置新的API相关。

首先新建两个上游upstream,写在http块内,便于下面区分:

1
2
3
4
5
6
7
8
9
upstream cpa_backend {
server 127.0.0.1:8317;
keepalive 32; # 多保留一些连接以防高并发
}

upstream cpa_usage_backend {
server 127.0.0.1:18317;
keepalive 8; # 可以少一点 毕竟用量查询请求不多
}

在下面再加一块针对WebSocket的协议升级,不过NGINX初始配置应该自带了:

1
2
3
4
map $http_upgrade $connection_upgrade {
default upgrade;
"" close;
}

随后新创建一部分server监听。根据官方文档,将CPA用到的API地址和CPAM用到的API地址分别反代:

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
server {

listen 127.0.0.1:8003 proxy_protocol;
listen 127.0.0.1:8004 http2 proxy_protocol;
server_name api.0d000721.xyz;

set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;

client_max_body_size 100m;

proxy_http_version 1.1; # 必须用HTTP/1.1 因后端不开启TLS选项
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;

proxy_set_header Host $host;
proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header Forwarded $proxy_add_forwarded;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;


# Codex Responses API:HTTP/SSE + WebSocket 都走 CPA
location = /v1/responses {
proxy_pass http://cpa_backend;

# server 层已经设置了 Upgrade / Connection / Host / X-Forwarded-* / timeout
# 这里不要单独只写一两个 proxy_set_header,否则会覆盖继承行为
proxy_request_buffering off;
}

# CPA-Manager / Usage Service 自己的接口
location = /health {
proxy_pass http://cpa_usage_backend;
}

location = /status {
proxy_pass http://cpa_usage_backend;
}

location = /setup {
proxy_pass http://cpa_usage_backend;
}

location ^~ /usage-service/ {
proxy_pass http://cpa_usage_backend;
}

# CPA HTTP 用量队列:必须交给 CPA 本体
location = /v0/management/usage-queue {
proxy_pass http://cpa_backend;
}

# CPA-Manager 提供的用量统计接口
location = /v0/management/usage {
proxy_pass http://cpa_usage_backend;
}

location ^~ /v0/management/usage/ {
proxy_pass http://cpa_usage_backend;
}

# CPA-Manager 提供的模型价格接口
location = /v0/management/model-prices {
proxy_pass http://cpa_usage_backend;
}

location ^~ /v0/management/model-prices/ {
proxy_pass http://cpa_usage_backend;
}

# 其他管理 API 仍交给 CPA 本体
location ^~ /v0/management/ {
proxy_pass http://cpa_backend;
}

# /management.html 必须交给 CPA 本体,而不是 CPA-Manager
location = /management.html {
proxy_pass http://cpa_backend;
}

# OpenAI 兼容 API、模型列表等默认走 CPA 本体
location / {
proxy_pass http://cpa_backend;
}
}

接着重启一下NGINX服务,访问https://api.0d000721.xyz/即可看到回应。管理面板在https://api.0d000721.xyz/management.html

登录管理面板后,首先需要进行CPA连接。不出意外的话会提示“当前面板由 Usage Service 托管”,我们只要填写CPA地址即可。

这里需要填写基于服务器本机的地址,如http://127.0.0.1:8317,而非暴露公网的https://api.0d000721.xyz!因为目前打开的是Usage Service的管理面板。理论上写https://api.0d000721.xyz也只是绕一圈,但别忘了我们上面没有为CPA和CPAM开启TLS,因此会出现协议错误的问题。只能老老实实写本地地址。

随后填一下CPA的管理密钥(非API密钥)。

WebSocket 配置

对于Codex而言,在~/.codex/config.toml下的模型配置中加一行:

1
supports_websockets = true

切换到WebSocket后体感快一点。