docs: 记录备案号更正,并记下子站缺备案号的遗留项

- xpcool.com 与 admin.xpcool.com 备案号更正为 黔ICP备2026003933号,
  两处生效点与 DEPLOY/日志同步记录;
- MEMORY.md 索引补一行「站点备案号」常驻信息,便于下次改号时一次找齐;
- 遗留:home / tool 两个子站目前完全没有展示备案号,待用户决定是否补。
This commit is contained in:
夏犀麟 2026-09-14 01:11:10 +08:00
parent 621acf12ef
commit b0b40aabfc
4 changed files with 144 additions and 2 deletions

View File

@ -14,3 +14,8 @@
2026-09-14 | DOC | 沉淀经验到 skill `uptime-kuma-sqlite-ops`:新增「告警不生效排查:先分三段」章节(① 有无事件触发 → ② 推送是否发出 → ③ 手机是否收到),新增两条 SSH 踩坑(回传 base64 的那条 ssh 不能夹带 `ls`/`echo`,否则 `base64 -d` 报 invalid input`scp ... 2>&1 | grep -v 噪音 && ssh ...` 因 grep 无匹配返回 1 而短路),并新增可复用自检脚本 `scripts/kuma-bark-check.sh`(变量化容器名与通知 id自带备份与自清理
2026-09-14 | DEP | **Bark 通知增强补丁正式部署并端到端验证通过**9-13 备好的补丁因沙箱拦截 SSH 一直未落地)。流程:逐个 scp 7 个文件icon/down/up.png、bark.js、status.xpcool.com.conf、deploy-bark-custom.sh、kuma-bark-verify.sh→ 远端执行部署脚本(备份 `docker inspect` 与 nginx conf → 素材落 `/data/www/bark-assets/` → 补丁落 `/data/uptime-kuma-patch/bark.js` 并做 `node --check` 语法门禁 → nginx reload → 重建容器带 `:ro` 挂载 → 校验 md5。结果补丁 md5 `98c586f988084b89e1b5452257442b08` 宿主机与容器内一致、挂载在(`RW=false`、9 处定制标记;端到端验证(临时监控 id=12 触发真实 DOWN时 Bark 日志收到完整定制参数 `icon=…/bark-assets/icon.png & level=critical & volume=5 & badge=auto & isArchive=1 & image=…/bark-assets/down.png`,对比部署前仅 `icon`(GitHub)+`group`+`sound` 三项;清理后监控恢复 9 个、关联 9 条、面板 302 正常。**部署包归档 `E:\CentOS\deploy-bark-custom\`(含 README**
2026-09-14 | FIX | 修 `deploy-bark-custom.sh` 两处隐患:① 补丁语法检查失败原先只打印错误、仍继续重建容器 → 改为 `exit 1` 中止(语法错会让 Kuma 整个通知模块挂掉);② 取图验证原先只看 HTTP 状态码,会被 Kuma SPA 的 `200 + index.html` 骗过(且 `nginx reload` 后旧 worker 仍在退出,请求会落到 `location /`)→ 改为 `sleep 3` + 校验 `content_type=image/png`。另 `sudo docker cp` 产生的 `/tmp/_bark_check.js` 属 root`rm` 需加 `sudo`
2026-09-14 | FIX | **排查并优化 read.xpcool.com 访问慢 —— 根因不在服务器,在前端资源传输**。read 是 **Flutter Web** 应用,首屏需下载 `main.dart.js` 12.75MB + `canvaskit.wasm` 6.76MB 等合计 **20.6MB**而应用侧Solon既未压缩也未设有效缓存上游仅给 `Cache-Control: max-age=600`)。仅改宿主机 `/data/nginx/conf.d/read.xpcool.com.conf`**未重启容器、零中断**):① 开启 gzip`gzip_types` 含 `application/wasm`、`comp_level 5`、**`gzip_proxied any` 必写**,否则 proxy_pass 的上游响应不压缩);② 分级缓存(`/canvaskit/*` 30d、构建产物 7d、`/` 不缓存以保换版及时);③ 静态资源 `proxy_hide_header Set-Cookie`(上游给每张 JS/WASM/图片都塞 `SOLONID`,静态资源不需要;**首页与 API 的 cookie 保持不变并已实测未误伤**)。公网实测首屏 **20.6MB → 6.04MB(省 71%**,服务端 TTFB 15ms。**排除项(均非瓶颈)**:应用内部响应仅 0.9ms、数据库 3.2MB/16 表、出口网络正常、负载 0.06
2026-09-14 | DOC | **拦下一次误改**`conf.yml` 的 `server.http.coreThreads: x5` / `maxThreads: x10` 初判为「无效数值」,查证 Solon 官方文档后确认 **`xN` 是合法语法 = CPU 内核倍数**jstack 实测正好 20 个 `smarthttp-` 线程4 核×5证明确实生效遂未动手。教训**框架配置里的可疑值先查文档,别凭直觉改**
2026-09-14 | CFG | 服务器补 **2GB swap**(原 swap=03.6G 内存跑 12 个容器是 OOM 隐患):`/swapfile` 已 swapon 并写入 `/etc/fstab``vm.swappiness` 60→10 并写入 `/etc/sysctl.conf`
2026-09-14 | DOC | read 提速部署包归档 `E:\CentOS\deploy-read\`nginx 配置 + README含完整实测表、三个坑、回滚命令与可选优化清单
2026-09-14 | CFG | **用户给出正式备案号:`黔ICP备2026003933号`**(此前站点挂的 `闽ICP备19024351号` 为旧值。xpcool.com 改 `src/config.ts``SITE.icp`(合规信息集中一处)→ 重建 → 重新部署上线,线上 JS 核对新号在、旧号零残留,页脚桌面/移动端均无溢出admin.xpcool.com 同域名需同步,改 `packages/preferences/src/index.ts``appCopyrightPreferences`(真正生效处)+ `@core` 框架默认值 + snapshot 三处push 后由 Gitea Actions 自动部署。**遗留**home.xpcool.com 与 tool.xpcool.com 两个子站目前**完全没有展示备案号**,已告知用户待其决定是否补

View File

@ -61,7 +61,7 @@
| service.xpcool.com | `service.xpcool.com:new` | 127.0.0.1:10100 | Go 后端xpcool-net连 xpcool-mysql |
| tool.xpcool.com | —(静态) | — | 前端工具站 |
| file.xpcool.com | `fbq` | 127.0.0.1:10881 | FileBrowser Quantum 只读下载 |
| read.xpcool.com | `qread` | 127.0.0.1:8082 | 阅读 legado 自托管 |
| read.xpcool.com | `qread` | 127.0.0.1:8082 | 阅读 legado 自托管。**2026-09-14 性能优化nginx 加 gzip + 分级缓存,首屏 20.6MB → 6.04MB(省 71%**,详见下方专节 |
| git.xpcool.com | `gitea` + `gitea-runner` | 0.0.0.0:3000 / 0.0.0.0:2222 | 代码托管与 CI |
| sub2api.xpcool.com | `sub2api` + postgres + redis | 127.0.0.1:18080 | — |
| code.xpcool.com | `code-server` | 127.0.0.1:8080 | 网页版 VS Code |
@ -73,7 +73,7 @@
### Uptime Kumastatus.xpcool.com2026-09-13 部署)
- 镜像 `louislam/uptime-kuma:2.5.3`2.x 稳定线1.x 已停维护v2 有破坏性变更,跨大版本需迁移数据库)。
- 启动参数:`--restart unless-stopped -p 127.0.0.1:3001:3001 -e TZ=Asia/Shanghai -v /data/uptime-kuma:/app/data -v /data/uptime-kuma-patch/bark.js:/app/server/notification-providers/bark.js:ro --memory 512m`**最后一个 -v 是 Bark 增强补丁挂载2026-09-13 加**;没部署前可省略)。服务器内存仅 3.7G**swap=0**,必须限内存,避免 OOM 波及同机其他容器。
- 启动参数:`--restart unless-stopped -p 127.0.0.1:3001:3001 -e TZ=Asia/Shanghai -v /data/uptime-kuma:/app/data -v /data/uptime-kuma-patch/bark.js:/app/server/notification-providers/bark.js:ro --memory 512m`**最后一个 -v 是 Bark 增强补丁挂载2026-09-13 加**;没部署前可省略)。服务器内存仅 3.7G,必须限内存,避免 OOM 波及同机其他容器。**2026-09-14 起已从 swap=0 补到 2G swap**,见「服务器 swap」节。
- **v2 首次启动是「选择数据库」引导页**(逻辑在 `/app/server/setup-database.js`,读 `data/db-config.json`),选 SQLite 即可之后进入创建管理员账号页。Uptime Kuma **没有找回密码入口**,密码丢失只能改数据库/清 2FA务必记牢。
- nginx 反代**必须透传 WebSocket**`proxy_http_version 1.1` + `Upgrade`/`Connection` 头),否则面板无限重连、状态刷不出来。
- **证书**:腾讯云免费 DVCN/SAN 均为 `status.xpcool.com`**有效期仅 3 个月(至 2026-12-12到期必须重新申请并替换**;落点 `/data/nginx/ssl/status.xpcool.com/`crt/pem/csr 644、key 600本地源 `E:\CentOS\ssl\status.xpcool.com_nginx\`。部署时用 `openssl x509 -pubkey | md5``openssl pkey -pubout | md5` 比对,确认证书与私钥配套。
@ -117,3 +117,32 @@
- **2026-09-14 部署实测**:补丁 md5 `98c586f988084b89e1b5452257442b08` 宿主机与容器内一致;`docker inspect` 确认挂载在(`/data/uptime-kuma-patch/bark.js -> /app/server/notification-providers/bark.js``RW=false`);临时监控触发真实 DOWN 后Bark 服务端日志收到带完整定制参数的推送(`icon=…/bark-assets/icon.png&group=Uptime-Kuma&sound=telegraph&level=critical&volume=5&badge=auto&isArchive=1&image=…/bark-assets/down.png`),对比部署前只有 `icon`(GitHub) + `group` + `sound` 三项。
- **⚠️ 验证静态资源别只看 HTTP 状态码**Kuma 的 SPA 对任何未知路径都返回 `200 + index.html`,只检查 code 会把「location 未生效」误判成成功;且 `nginx reload` 是优雅重启,旧 worker 退出期间请求仍可能落到 `location /`。故取图验证要先 `sleep 3` 再校验 `content_type=image/png`
- **⚠️ 手机上需允许「重要警告」**`level=critical` 要真正穿透静音/专注,需在 Bark App 的通知设置里开启重要警告权限,否则仍会被系统静音。
### read.xpcool.com 访问提速2026-09-14
**根因不在服务器,在前端资源传输。** read 是 **Flutter Web** 应用(非 Vue/React SPA产物极大而应用侧Solon既没压缩也没缓存
| 资源 | 原始 | gzip 后 | 压缩率 |
|---|---|---|---|
| main.dart.js | 13,369,421 B | 3,420,588 B | 74.4% |
| canvaskit.wasm | 7,083,768 B | 2,879,449 B | 59.4% |
| skwasm.wasm | 3,551,820 B | 1,529,141 B | 57.0% |
| **首屏合计** | **约 20.6 MB** | **约 6.04 MB** | **71%** |
**只改一个文件**`/data/nginx/conf.d/read.xpcool.com.conf`(未重启容器、零中断):
1. **`gzip on``gzip_types` 必须含 `application/wasm`**`gzip_comp_level 5`5 与 9 压缩率差 <2%CPU 更省**`gzip_proxied any` 必写** proxy_pass不写则上游响应不压缩)。
2. **分级缓存**`/canvaskit/*` → 30 天;`main.dart.js` 等构建产物 → 7 天;**`/` 不缓存**index.html 带 `serviceWorkerVersion`,每次必须拿最新才能换版)。
3. **仅静态资源 `proxy_hide_header Set-Cookie`**:上游给每张 JS/WASM/图片都塞 `SOLONID`,静态资源并不需要;隐去后响应变可缓存,为接 CDN 铺路。**首页与 API 的 cookie 保持原样**(已验证)。
**三个坑(均实际踩过)**
- **`conf.yml``coreThreads: x5` / `maxThreads: x10` 不是笔误**。查证 Solon 官方文档:**`xN` 是合法语法 = CPU 内核倍数**jstack 实测 20 个 `smarthttp-` 线程4 核×5配置真实生效。**别凭直觉改**,要验证就数线程 `docker exec qread jcmd <pid> Thread.print`
- **不能只看状态码判断压缩**:容器内直连 8082 带 `Accept-Encoding: gzip` 仍返回 `Content-Length: 13369421` —— 压缩是 nginx 做的、不是应用做的,必须经 443 测才有 `content-encoding: gzip`
- **别重复加 `Cache-Control`**`expires 7d` 已自动生成 `Expires` + `Cache-Control`,再 `add_header` 会出重复头。
**回滚**`sudo cp /data/nginx/conf.d/read.xpcool.com.conf.bak.20260914-010244 /data/nginx/conf.d/read.xpcool.com.conf && sudo nginx -s reload`。部署包归档 `E:\CentOS\deploy-read\`(含 README 与完整实测数据)。
**未做的可选优化**:接 CDN收益最大需配 DNS、编译 nginx brotli 模块(再省 15~20%,风险高)、开 Solon 虚拟线程(需版本 ≥2.7.3,要重启容器)、静态资源提取到磁盘 + `gzip_static`CPU 本非瓶颈)。
**另注**`main.dart.js` 达 12.75MB,正常 Flutter Web release 构建通常 1.5~3MB怀疑镜像构建未充分优化 —— 属上游镜像范畴,未擅改。
### 服务器 swap2026-09-14 新增)
内存仅 **3.6G** 却跑 12 个容器MySQL 435M / Gitea 479M / qread 370M / Kuma 115M…原先 **swap=0**,内存峰值时无缓冲会直接 OOM 杀进程。已补 **2GB swapfile**`/swapfile``fallocate`→`chmod 600`→`mkswap`→`swapon`)并写入 `/etc/fstab``vm.swappiness` 由 60 调为 **10**(避免过早换出反而拖慢响应),已入 `/etc/sysctl.conf`

View File

@ -29,6 +29,8 @@
| home.xpcool.com | 前端服务台(公开服务入口) | `../home.xpcool.com/.workbuddy/memory/CHANGELOG.md` | 本地 git init/commit远程待建 |
| xpcool.com | 主域名:随机壁纸站(浏览器实时生成,可导出 4K中英日韩 + 日夜主题) | `../xpcool.com/.workbuddy/memory/CHANGELOG.md` | 2026-09-13 上线;本地 git init/commit远程待建 |
> **站点备案号(同域名子站通用):`黔ICP备2026003933号`** —— 集中写在 xpcool.com `src/config.ts``SITE.icp`,跳转核验 `https://beian.miit.gov.cn/`admin.xpcool.com 在 `packages/preferences/src/index.ts``appCopyrightPreferences`。改号时两处一起改。**待办**home / tool 两个子站尚未展示备案号。
## 命中流程
判断涉及哪个项目 → 读该项目 CHANGELOG 头部 1015 条 → 处理后于顶部追加本次记录 → 新增项目时同步更新上方索引表。

View File

@ -0,0 +1,106 @@
# read.xpcool.com — 轻阅读 Web 端
# 后端Docker qread 容器,宿主端口 8082
#
# 2026-09-14 性能优化:
# 前端为 Flutter Web 产物main.dart.js 达 12.75MB、canvaskit.wasm 达 6.76MB
# 且应用侧未做任何压缩与缓存(实测响应头无 Content-Encoding / Cache-Control
# 本次开启 gzip实测可省约 70% 流量)并分级加缓存头。
server {
listen 80;
server_name read.xpcool.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name read.xpcool.com;
ssl_certificate /data/nginx/ssl/read.xpcool.com/read.xpcool.com_bundle.crt;
ssl_certificate_key /data/nginx/ssl/read.xpcool.com/read.xpcool.com.key;
client_max_body_size 256m;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
# ---------- gzip 压缩 ----------
# 应用侧Solon不压缩静态资源全部由 nginx 承担。
# 实测 gzip -6main.dart.js 13.37MB→3.16MBcanvaskit.wasm 6.76MB→2.73MB。
gzip on;
gzip_comp_level 5; # 5 已接近最优压缩率,比 9 明显省 CPU
gzip_min_length 1024;
gzip_vary on; # 按 Accept-Encoding 分别缓存,避免代理串味
gzip_proxied any; # 上游proxy_pass响应同样压缩
gzip_buffers 32 8k; # 大文件压缩时加大缓冲,减少写盘/发送次数
gzip_http_version 1.1;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/x-javascript
application/json
application/xml
application/wasm # Flutter CanvasKit / SkWasm 引擎
image/svg+xml
font/woff
font/woff2;
# text/html 为 nginx 默认包含,无需重复声明
# ---------- Flutter 引擎资源 ----------
# 体积最大、内容随引擎版本固定 → 长缓存,命中后完全不走网络。
location ^~ /canvaskit/ {
proxy_http_version 1.1;
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;
# 上游不压缩,显式清空避免双重压缩
proxy_set_header Accept-Encoding "";
proxy_pass http://127.0.0.1:8082;
# 静态资源不需要会话,隐去无用 cookie
# 既省 header 体积,也让响应可被正常缓存(带 Set-Cookie 的响应在多数代理/CDN 下不可缓存)
proxy_hide_header Set-Cookie;
expires 30d;
access_log off;
}
# ---------- Flutter 构建产物 ----------
# 文件名固定(无内容 hash故用中等缓存配合 Flutter 自带 service worker 换版。
location ~* ^/(main\.dart\.js|flutter_bootstrap\.js|flutter\.js|flutter_service_worker\.js|manifest\.json|favicon\.png|assets/|icons/) {
proxy_http_version 1.1;
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;
proxy_set_header Accept-Encoding "";
proxy_pass http://127.0.0.1:8082;
proxy_hide_header Set-Cookie;
expires 7d;
access_log off;
}
# ---------- 应用接口与页面 ----------
# 注意:/ 返回的 index.html 带 serviceWorkerVersion不能缓存保持原样。
location / {
# WebSocket 支持(书源调试、实时推送依赖)
proxy_http_version 1.1;
set $conn_upgrade "close";
if ($http_upgrade != "") {
set $conn_upgrade "upgrade";
}
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $conn_upgrade;
proxy_pass http://127.0.0.1:8082;
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;
}
}