Files
blog/blog-admin/部署清单.md
T
zqlit a74b3c7127
Deploy to Production / pre-check (push) Successful in 58s
Deploy to Production / build (push) Successful in 4m3s
Deploy to Production / deploy-edgeone (push) Successful in 3m48s
Deploy to Production / finalize (push) Successful in 26s
Deploy to Production / notify-failure (push) Skipped
归档 artalk-cf 评论后端 + rss-robot 到 blog-admin(含技术选型/模块分布 README)
2026-10-04 08:45:40 +08:00

289 lines
9.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 部署清单(照着敲,约 10 分钟)
在 `artalk-cf` 目录里执行。**第 9 步(域名)有个必须先想清楚的坑**,其余都是机械操作。
需要你有的东西:Cloudflare 账号、Node.js(本机已有 22.x)、一个能连上 Cloudflare 的网络。
---
## 0. 先确认环境
```bash
cd artalk-cf
npm install
node node_modules/typescript/bin/tsc --noEmit # 应该没有任何输出
```
> 这台机器上 npm 可能被沙箱网络打断(`stub` 装不全)。若报 `Cannot find module`,
> 重跑 `npm install` 直到 `node_modules/wrangler/package.json` 能读出版本号。
---
## 1. 登录 Cloudflare
```bash
npx wrangler login
```
会弹出浏览器让你授权(这一步必须你自己点,我代不了)。
成功后会显示 `Successfully logged in.`
检查:
```bash
npx wrangler whoami
```
---
## 2. 建 D1 数据库
```bash
npx wrangler d1 create artalk-cf
```
输出里会有一行 `database_id = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"`,**复制它**。
---
## 3. 把 database_id 填进配置
编辑 `wrangler.toml`,把这一行改掉:
```toml
[[d1_databases]]
binding = "DB"
database_name = "artalk-cf"
database_id = "00000000-0000-0000-0000-000000000000" # ← 换成刚才复制的那串
```
同一文件里再确认这几项是否符合你的情况:
```toml
[vars]
SITE_DEFAULT = "优世界" # 必须和博客 hugo.toml 里的 site 一致
SITE_URL = "https://usj.cc"
ADMIN_NAME = "小赵"
ADMIN_EMAIL = "z@usj.cc"
ALLOWED_ORIGINS = "https://usj.cc,https://www.usj.cc,https://post.usj.cc,http://localhost:1313"
```
> `ALLOWED_ORIGINS` 少了博客域名的话,浏览器会因 CORS 拒绝评论请求(评论区一直转圈)。
---
## 4. 写入两个机密(不要写进文件)
```bash
# 签 token 的密钥:先生成一串随机的
node -e "console.log(require('crypto').randomBytes(48).toString('base64url'))"
npx wrangler secret put TOKEN_SECRET # 粘贴上面那串
npx wrangler secret put ADMIN_PASSWORD # 输入你要用的后台密码
```
(本地开发时改用 `.dev.vars`:`cp .dev.vars.example .dev.vars` 然后改值。)
---
## 5. 建表
```bash
npx wrangler d1 execute artalk-cf --remote --file=./schema.sql
```
应该看到若干条 `🚣 Executed 8 commands` 之类的成功输出。
核对:
```bash
npx wrangler d1 execute artalk-cf --remote --command \
"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;"
```
应含:`captcha_challenges captcha_passes comments notifies pages rate_limits settings sites users votes`
---
## 6. 部署
```bash
npx wrangler deploy
```
输出末尾会给一个地址:
```
Uploaded artalk-cf (x.xx sec)
https://artalk-cf.<你的账号子域>.workers.dev
```
**把它记下来**,下面用 `<BASE>` 代替。
---
## 7. 导入评论数据(**必须在初始化管理员之前**)
```bash
python tools/import_artrans.py # 默认只导「优世界」,跳过朋友那三个站
bash tools/import-out/run.sh --remote
```
脚本会打印:
```
源文件 4048 条,按站点筛选后 3440 条 -> 归入站点「优世界」
用户 491 个
页面 91 个
评论 3339 条(其中回复 1791 条)
跳过 101 条:page_key 为空 101、昵称或邮箱为空 0、id 非法 0
```
最后 `run.sh` 会跑一段自检,打印各表条数,对一下:
`sites 1 / pages 91 / users 491 / comments 3339 / replies 1791`
> ⚠️ **两个坑**
> 1. `00-reset-and-site.sql` 会**清空 comments/pages/users/sites 四张表**——
> 所以它会把第 8 步建的管理员一起删掉。**顺序必须是「先导入、后初始化」**。
> 库里已有数据时也别再跑,会被清空。
> 2. `wrangler d1 execute --remote` 会先问一次确认,脚本里已经带了 `-y`。
> 如果你是手动逐条敲命令,漏了 `-y` 会直接报错退出。
---
## 8. 初始化站点与管理员
```bash
curl -X POST <BASE>/api/v2/setup
```
期望返回:
```json
{"msg":"Success","site":"优世界","admins":["admin@200181.xyz"],"reseted":false}
```
它会建默认站点、把 `ADMIN_NAME/EMAIL/PASSWORD` 写成管理员(密码存 PBKDF2 哈希)。
**立刻验证管理员能登录**(账号名或邮箱都行):
```bash
curl -X POST <BASE>/api/v2/user/access_token \
-H 'Content-Type: application/json' \
-d '{"email":"admin","password":"你刚设的密码"}'
```
返回里有 `"token":"..."` 就对了。**没有 token 说明第 4 步的密码没写进去。**
> 忘了密码想重设:`curl -X POST "<BASE>/api/v2/setup?force=<TOKEN_SECRET>"`,
> `TOKEN_SECRET` 就是你第 4 步写进去的那串(拿它当"部署密钥"用)。
---
## 9. ★ 域名:这一步有个坑,先想清楚
### 问题
**Cloudflare Worker 的自定义域名要求「域名的 NS 托管在 Cloudflare」。**
官方文档写得很明确:绑定自定义域名时,Cloudflare 会自动创建 DNS 记录和 SSL 证书——
这需要 zone 在 Cloudflare 里。外部 DNS 用 CNAME 直接指过去,社区反馈是"各种奇奇怪怪的错误"。
而 **`usj.cc` 的 NS 在 DNSPod**(还挂着又拍云 + 腾讯云 EdgeOne 的调度)。
**千万不要为了评论 API 把整站 NS 搬去 Cloudflare**——那会把现有的国内双 CDN 链路一起弄坏。
### 四个选项
| 选项 | 做法 | 代价 | 建议 |
|---|---|---|---|
| **A. 另用一个 CF 托管域名** | 用另一个域名(新注册的也行,便宜)把 NS 放到 Cloudflare,绑 `artalk-cf.<那个域名>` | 一年域名钱 | ✅ **推荐** |
| B. 先用 workers.dev | 第 6 步的地址直接当正式地址 | **大陆访问不通**,只能自测 | 仅用于验证功能 |
| C. DNSPod 加 CNAME | `artalk-cf` CNAME 到 `<worker>.workers.dev` | 官方不支持,可能不通/证书异常 | 可以试,别当正式方案 |
| D. 整站 NS 迁到 Cloudflare | usj.cc → Cloudflare | **会破坏又拍云/EdgeOne 调度** | ❌ 不要 |
### 选了 A 之后怎么做
1. 新域名加进 Cloudflare → 按提示把 **NS 改到 Cloudflare**
2. 打开 `wrangler.toml`,取消注释并改成你的域名:
```toml
[[routes]]
pattern = "artalk-cf.你的域名"
custom_domain = true
```
3. `npx wrangler deploy`
4. 把域名加进 `ALLOWED_ORIGINS` 后再 deploy 一次
5. `curl https://artalk-cf.你的域名/api/v2/healthz` 应返回 `{"ok":true,...}`
---
## 10. 接到博客上(改一行 + 重新发布)
编辑 `E:\GitHub\blog\hugo.toml`:
```toml
[params.artalk]
server = "https://artalk-cf.你的域名" # ← 只改这一行
site = "优世界"
```
然后按你平时的流程发布(写作后台点发布,或按 `hugo-writeserver-publish-ops` 里那套精确发布命令)。
**前端一个字符都不用动**——客户端调的就是 `${server}/api/v2/...`,
`pageKey` 用 `.RelPermalink`(`/20210911.html`),和 D1 里的 `page_key` 完全对应。
---
## 11. 验收
```bash
bash tools/smoke.sh https://artalk-cf.你的域名
```
然后拿 token 再跑一遍后台用例:
```bash
TOKEN=$(curl -s -X POST https://artalk-cf.你的域名/api/v2/user/access_token \
-H 'Content-Type: application/json' \
-d '{"email":"z@usj.cc","password":"你的密码"}' | node -e "let s='';process.stdin.on('data',d=>s+=d).on('end',()=>console.log(JSON.parse(s).token))")
TOKEN=$TOKEN bash tools/smoke.sh https://artalk-cf.你的域名
```
### 手动验收清单
- [ ] 打开 `https://artalk-cf.你的域名/sidebar/` —— 能看到 Artalk 后台登录页
- [ ] 用邮箱 + 密码登录进去,能看到 **3339 条评论**
- [ ] 打开博客任意一篇有评论的文章 —— 评论、回复层级、博主徽章都对
- [ ] 打开 `/comment.html`(994 条那篇)—— 分页/加载更多正常
- [ ] 发一条新评论 —— 立刻出现
- [ ] 后台改一条评论的置顶/审核状态 —— 前台刷新后生效
---
## 12. 出问题怎么查
| 现象 | 原因 | 处理 |
|---|---|---|
| 评论区一直转圈 | CORS:`ALLOWED_ORIGINS` 没有博客域名 | 加上域名重新 deploy |
| `401 Unauthorized` 登录失败 | 第 4 步密码没写进去 | `npx wrangler secret put ADMIN_PASSWORD` 后重新跑第 7 步 |
| 后台打不开、404 | `/sidebar/` 静态资源没上传 | 确认 `artalk-cf/public/sidebar/index.html` 存在,重新 deploy |
| 评论为空但后台有数据 | `page_key` 对不上 | 检查博客的 `pageKey` 是不是 `/xxx.html`;D1 里 `SELECT page_key FROM comments LIMIT 5` 比对 |
| 部分回复层级错乱 | 导入时 rid 没回填 | 确认 `run.sh` 里 `04-rid-fix-*.sql` 都执行过了 |
| 报 `Too many requests` | 限流生效(同 IP 60 秒 5 条) | 正常行为;管理员发表不受限 |
| 前端弹版本不匹配黄条 | 客户端版本 ≠ 服务端上报版本 | 服务端固定报 `2.8.7`;若你把博客的 `Artalk.js` 升级了,改 `src/routes/public.ts` 的 `SERVER_API_VERSION` |
| 大页面(994 条评论)超时 | Workers 免费版 CPU 10ms | 调小客户端 `pagination.pageSize`,或上 Workers Paid |
实时日志:
```bash
npx wrangler tail
```
---
## 附:也可以让我代跑
如果你不想自己敲,可以给我一个 **Cloudflare API Token**(权限只需
`Workers Scripts: Edit` + `D1: Edit` + `Account Settings: Read`),我可以直接执行第 2~8 步。
用完请立刻在 Cloudflare 后台把那个 token 删掉。
第 1 步(浏览器登录授权)和第 9 步(改 NS)无论如何都得你自己来。