6.4 KiB
Token 排行榜部署(独立域名)
推荐单独建一个网站,例如 token.example.com。Sub2API 那份 location ^~ / 不用改。
页面请求同源 /api/v1/...,由这个新站点把 /api/ 反代到本机 127.0.0.1:8080。局域网构建已把 Admin API Key 打进前端 JS。
1. 1Panel 建站
- 网站 → 创建网站 → 静态网站(或 PHP 静态)
- 域名填你要的,例如
token.example.com - 证书按你现有流程申请
- 记下「网站目录」,一般是:
/www/sites/token.example.com/index
2. 静态文件放到哪
把 dist/ 里面的文件 放到网站目录根:
/www/sites/token.example.com/index/index.html
/www/sites/token.example.com/index/assets/...
不要多套一层 dist/ 或 www/。
sudo rsync -a --delete www/ /www/sites/token.example.com/index/
或解压部署包:
tar -xzf token-list-deploy-YYYYMMDD.tar.gz
sudo rsync -a --delete token-list-deploy/www/ /www/sites/token.example.com/index/
3. nginx 怎么改
打开新站点配置文件,保证有这两段,location /api/ 必须在 location / 前面:
location /api/ {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_read_timeout 300s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location / {
try_files $uri $uri/ /index.html;
}
保存并重载。访问 https://token.example.com/(换成你的域名)。
1Panel 也可以:网站 → 反向代理 → 添加 /api → 目标 http://127.0.0.1:8080。效果一样。
4. 不要直接让页面跨域打 Sub2API
浏览器里的请求必须是新域名自己的 /api/v1,由 nginx 转到 8080。不要把 VITE_API_BASE 改成 https://sub2api.example.com/api/v1,否则会碰上 CORS。
5. 百炼 Token Plan 额度探针(可选)
分组页首的「阿里云百炼 · Token Plan」卡片读取同源静态文件 /data/bailian.json,由本仓库 bailian-probe.py(Python 3 标准库,零依赖)定时生成。Key 与 Cookie 只在服务器落盘,永远不进前端与 git。
背景:百炼个人版官方文档不提供 5h/7d 窗口查询 API,公开可用的是控制台网关(鉴权 = 控制台登录 Cookie,会过期)。探针另带 apikey 模式用于验证 sk-sp Key 是否存在 usage 端点(尚未证实)。
# 1) 脚本与配置
sudo mkdir -p /opt/bailian-probe
sudo cp bailian-probe.py /opt/bailian-probe/
sudo cp bailian-probe.env.example /etc/bailian-probe.env
sudo chmod 600 /etc/bailian-probe.env
# 2) 取 Cookie:浏览器登录 bailian.console.aliyun.com → F12 网络面板 →
# 打开「Token Plan > 我的订阅」→ 复制发往 bailian-cs.console.aliyun.com
# 的 api.json 请求的完整 Cookie → 填入 /etc/bailian-probe.env 的 BAILIAN_COOKIE
# 并把 BAILIAN_OUT 改成你的站点目录,例如:
# BAILIAN_OUT=/www/sites/token.example.com/index/data/bailian.json
# 3) 手动跑一次确认出图
sudo python3 /opt/bailian-probe/bailian-probe.py
curl -s https://token.example.com/data/bailian.json | head -c 400
# 4) 定时:systemd(bailian-probe.service + .timer 拷到 /etc/systemd/system/)
sudo systemctl daemon-reload && sudo systemctl enable --now bailian-probe.timer
# 或 crontab(*/7 素数分钟避开整点共振):
# */7 * * * * /usr/bin/flock -n /run/bailian.lock /usr/bin/python3 /opt/bailian-probe/bailian-probe.py >> /var/log/bailian-probe.log 2>&1
要点:
data/在站点根内,nginx 静态即可,不需要新增 location;探针失败会保留上次快照并标stale,页面照常渲染。- Cookie 过期时卡片显示「请在服务器更新 BAILIAN_COOKIE」(错误归因
unauthorized),其余数据不受影响。 - 快照只含百分比 / Credits / 时间戳,不含任何凭证,可公开访问;介意的话给
/data/加一条 allow 内网的 nginx 规则。
6. 一键脚本 deploy.sh(10.1.192.225 现行部署)
当前生产:宿主机 root@10.1.192.225,部署根 /usr/dcits/token-list-share/(www/ 站点根、probe/ 探针脚本、.env 在上一级且权限 600),宿主机 nginx 监听 18081(Sub2API 容器占 18080),/api/ 反代 127.0.0.1:18080;探针配置 /etc/bailian-probe.env(凭证留在 /etc,不进应用目录),快照 www/data/bailian.json。本机公钥已加入 root authorized_keys,脚本在本机 Git Bash 里直接跑:
bash deploy.sh # 构建并发布前端(= web,自动保留 data/ 快照目录)
bash deploy.sh cookie # 交互粘贴新百炼 Cookie,写入后立即试跑并回显结果
bash deploy.sh probe # 更新探针脚本/systemd 单元并试跑(timer 每 5 分钟)
bash deploy.sh nginx # 刷新 nginx 站点配置并 reload
bash deploy.sh auth # 交互式设置 Basic Auth 用户名/密码(不回显),整站开启认证
bash deploy.sh auth off # 关闭 Basic Auth
bash deploy.sh status # 定时器、快照、各 URL HTTP 自检
bash deploy.sh all # nginx + web + probe
Basic Auth 在 nginx 层整站生效(页面、/api/、/bailian-admin/、/data/ 都要登录),浏览器输入一次后同域请求自动带凭证,前端无需改动;账号密码以 apr1 哈希存在服务器 /etc/nginx/token-list.htpasswd(640,密码经 600 临时文件透传,不进命令行/进程列表)。nginx 子命令每次按该文件是否存在自动决定开/关认证,所以换机器或重刷配置不会丢开关。
- Cookie 经 600 权限临时文件透传,不出现在远端命令行/进程列表;
.env同步到站点根上一级(www/之外,nginx 发不出去)。 - 可用
DEPLOY_HOST/REMOTE_DIR/SITE_PORT/SUB2API_UPSTREAM环境变量覆盖默认目标。
probe 还会安装 reset-card-server.service(deploy/reset-card-server.py,只绑 127.0.0.1:18082),nginx 经 /bailian-admin/ 反代:分组页的重置卡「使用」按钮带 Admin Key 调它,服务端先 reset-card/list 校验卡归属再代发 reset-card/use,成功后重跑探针。探针本体永不调用 use。 前端入口默认 CSS 隐藏,需在分组页控制台执行 localStorage.setItem('bailian-reset-card','1') 后刷新(或临时 document.documentElement.dataset.resetCards='1')才显示。