---
id: 001
title: 需要第二台测试服务器（staging）
status: closed
labels: [infra, cost, risk]
assignee: team-lead
created_at: 2026-04-23
closed_at: 2026-04-23
---

# #001 需要第二台测试服务器（staging）

## 背景

当前只有 epsilon (`112.124.27.213`, 2C4G, i-bp1iswr9bmkv3qh89965) 一台在跑 xiangqin，且直接是**生产**。

风险：

- **所有 deploy 直接打生产**：`bash scripts/deploy.sh` 跑到一半挂了，影响真实用户（M4 起可能有真付费用户）
- **schema migration 无法预演**：`_drop_exposure_tables` / `_migrate_profile_columns` 这种破坏性变更，在生产第一次跑心里没底
- **OpenClaw hook 推送 E2E 联调没环境**：测试 agent gateway 通知推到真人的 WeChat / Telegram，得有地方跑不污染生产
- **备份恢复演练无处做**：`scripts/restore.sh --dry-run` 当前只在 epsilon 自身测（不算真演练）

## 目标

加一台 **staging 服务器**：规格可以比生产小，但**生产的全套 systemd + nginx + 备份链路都能跑**。

## 候选服务器（来自 vault `aliyun/ecs/`）

vault 里已有 4 台空闲 ECS（2026-04-22 老板确认旧业务下线可重新分配）：

| 别名 | instance_id | public_ip | 到期 | 备注 |
|---|---|---|---|---|
| alpha | i-bp17gxpssxlqi9ig7xxh | 120.27.148.143 | 2026-05-01 | 原 jarvis-browser |
| beta | i-bp19va03m1nu4oahb1k1 | 47.111.181.28 | 2026-05-11 | 原 jarvis-openclaw-staging（名字最契合） |
| gamma | i-bp1ab0r4qnexg1f7soxh | 47.114.79.9 | 2026-05-11 | 原 matchmaker（已停）|
| delta | i-bp1iovf03vzq8d7ah0od | 118.31.226.214 | 2026-05-01 | 原 jarvis-preview |

**规格待查**（需跑 `aliyun ecs DescribeInstances` 或翻控制台）：`host-cli/workspace/fleet/aliyun-ecs.*.json` 里可能有 CPU / 内存 / 月费。

## 推荐 / 倾向

按候选别名语义，**beta**（原名 `jarvis-openclaw-staging`）最契合新用途。但要先确认：

1. 规格够不够（xiangqin 生产是 2C4G，staging 可降一档但不能太小以至于 sqlite + uvicorn 跑不动）
2. 到期时间（alpha / delta 到 2026-05-01 就到期了，要么续费要么不选）
3. 月费 vs 预算

## 依赖 / 阻塞

- 决定用哪台后：
  - vault 里改 resource `current_use` 字段（alpha → staging-xiangqin）
  - 写 `scripts/deploy-staging.sh`（参数化 host）
  - 写 `scripts/provision.sh` 把 systemd + nginx + uv + 目录结构一键装上
  - CI `docs` job 不动，但考虑是否加 `deploy-staging` job 自动推代码到 staging

## 讨论

### 2026-04-23 18:00 @claude

扫了 vault，候选 4 台已空闲。规格信息在 `host-cli/workspace/fleet/` 里更详细（当前 issue 作者没 clone 那个 repo，等老板补充或给路径）。

倾向 **beta**（别名语义最直接），但需老板从候选选一台 + 确认规格够 + 续费策略。

下次讨论议程：

1. 四台里选哪台？
2. 续费到什么时间？
3. staging 要不要公网直接暴露（有 80/443 开放）还是只 SSH 内网访问？
4. 数据库：staging 定期从 prod dump 同步，还是独立造假数据？

### 2026-04-23 19:30 @yarn（老板）

"这几台备注都有问题啊，其他备注的信息都过时了，都没有被占用才对。然后有一台是你之前拿来相亲拿来当生产用的，你现在挑一台租金便宜一点的，因为生产的那个很贵 500。"

→ 定调：所有 4 台实际都空闲（vault 备注已过时），挑最便宜的。

### 2026-04-23 19:40 @claude — 选 alpha

实例规格对比（按月费估算从低到高）：

| 别名 | instance_type | 规格 | 估算月费 | 到期 |
|---|---|---|---|---|
| **alpha ⭐** | ecs.t6-c1m1.large | 1C1G | ~30-50 元 | 2026-05-01 |
| delta | ecs.t6-c2m1.large | 2C1G | ~60-90 元 | 2026-05-01 |
| beta / gamma | ecs.g6.xlarge | 4C16G | ~500-1000 元 | 2026-05-11 |

（epsilon 生产实际是 `ecs.t6-c1m2.large` = 1C2G，之前代码里 "2C4G" 的说法也过时了）

**定 alpha**：
- 月费最低（~30-50 元）
- 1C1G 跑 xiangqin staging（sqlite + uvicorn + nginx）够
- 5-01 到期续费时保持最小规格即可
- vault metadata `current_use` 已更新为"分配给 xiangqin staging"

剩余 3 个待决项（本 issue 不关，等 staging 落地时再评论）：

1. alpha 规格 1C1G 和 prod 1C2G 略有差异（内存少 1GB）——实测 xiangqin 启动占用，必要时升到 1C2G
2. 公网 vs 仅 SSH：staging 建议也开 80/443（和 prod 对称，便于测跨网络）但用独立子域（如 `staging.xq.agentaily.com`）避免污染
3. 数据：建议**独立造假数据**（不从 prod dump，防敏感数据意外泄露到 staging）

### 行动清单

- [x] vault `alpha` `current_use` 更新指向本 issue（已 commit）
- [x] 参数化 `scripts/provision.sh` 支持 `epsilon | alpha`（不新建 `-staging.sh`）
- [x] 参数化 `scripts/deploy.sh` 支持 `epsilon | alpha`（同上）
- [ ] alpha 续费策略：2026-05-01 前老板决定（保留 or 换更便宜）
- [x] 上线后本 issue close → archive

### 2026-04-23 21:50 @claude — 落地完成

- SSH 直通，机器无业务残留，跳过整机重置
- `scripts/provision.sh alpha` 跑通：hostname=xiangqin-alpha / nginx / uv / xiangqin user / aliyun cli / systemd drop-in `override.conf`（alpha 专属：sms=mock payment=mock BASE_URL=http://120.27.148.143 独立 PHONE_SALT）
- `scripts/deploy.sh alpha` 跑通：rsync 源码 + uv sync + systemctl restart
- 验证：
  - ssh alpha curl 127.0.0.1/health → 200
  - 外网 http://120.27.148.143/health → 200
  - `xq --endpoint http://120.27.148.143 health` → 200 `{"status":"ok","version":"0.3.1"}`
- 修了 deploy.sh smoke test 的 race（`sleep 2` 太短 → 最多 15s 重试等 uvicorn ready）

副带发现（已记到 issue #003，独立处理）：**epsilon 生产 systemd 没配 PHONE_SALT，全程跑默认 `dev-salt-not-for-prod`**。不影响 alpha 落地，但需在 epsilon 滚一次合规的 salt。

续费 2026-05-01 那条老板到期前决定，本 issue 不卡。
