16 KiB
16 KiB
xpcool.com 生产环境 · 部署与运维手册
从 MEMORY.md 拆出(2026-09-13),存放服务器、容器、站点、安全加固与本机工具链坑位等细节。 MEMORY.md 只保留规则与索引。
生产部署(腾讯云 193.112.118.168,SSH 22025/xxcool,Docker+宿主机 Nginx)
- 站点落点:前端静态 →
/data/www/<域名>/;nginx 配置 →/data/nginx/conf.d/<域名>.conf(80→301→443 + 反代/静态);证书 →/data/nginx/ssl/<域名>/<域名>_bundle.crt|.key(本地源:E:\CentOS\ssl\<域名>_nginx/,2026-09-13 核对;证书只放_bundle.crt+.key,.csr/.pem一并留存便于比对)。 - service 后端容器:
service.xpcool.com:new,127.0.0.1:10100:10100,网络xpcool-net,env:GF_GCFG_ENV=prod+DB_DSN=mysql:service:xxx@tcp(xpcool-mysql:3306)/service?...(必须带 mysql: 类型前缀)+JWT_SECRET;容器内必须有manifest/config/config.yaml(基础配置),否则 GF 启动报「找不到 config」;构建目录/data/deploy/projects/service.xpcool.com/(main + manifest/config + resource,Dockerfile 用 COPY manifest/config 整体拷贝)。 - DB:
xpcool-mysql容器(root 密码见该容器 env),库名service,种子执行顺序 003→004→004b→007(服务器表结构旧,必须先 003 加列;导入用sudo sh -c 'docker exec -i xpcool-mysql mysql ... < file'宿主机重定向)。 - 权限映射:admin_menu type=2 行的 path 必须匹配实际路由(现为
POST /api/service/admin/...,见 manifest/sql/007_menu_permissions_v3.sql)。 - 文件下载站(2026-09-03 上线,当晚迁移):
file.xpcool.com= FileBrowser Quantum 容器fbq(gtstef/filebrowser:stablev1.5.5,127.0.0.1:10881→80,restart unless-stopped,/data/share:/srv:ro只读挂载,数据卷/data/filebrowser-q:config.yaml+database.db+tmp,属主=镜像 uid1000)+ nginx 反代。要点:初始凭据 admin/admin(首登后立即改密);配置走config.yaml(sources/cacheDir),管理走网页 UI;API 与原版不兼容(需用户建 long-live token,/swagger 亦需);镜像默认非 root(uid1000);原版 filebrowser(容器filebrowser/10880/db/data/filebrowser/database)已于 2026-09-01 归档、现已停用保留回滚;Quantum v2.0 beta 权限模型改 per-source(view/download/modify/create/delete)。改密/建只读账号/临时分享(过期+密码+匿名)均在网页 UI。 - SSH 凭据/密码不入库,需要时询问用户或查对话记忆;远程批量命令用 paramiko 脚本(
%TEMP%\wb_deploy\ssh_exec.py,支持第 2 参数超时秒数),docker build 用服务器端 nohup+日志轮询防超时。(2026-09-11 密钥轮换后更新):当前登录 = 本地~/.ssh/xpcool_ed25519(ed25519,注释 xpcool-server-20260904)→xxcool@193.112.118.168:22025(root 被拒;密码登录已禁);旧CentOS.pem(RSA,对应服务器公钥skey-q6pq6jb3)已作废并从 authorized_keys 移除(因私钥误提交 Gitea 事件而轮换),服务器 authorized_keys 另存 2 把钥(mcp-server-manager@local、xxcoolwork@gmail.com)为其他用途、保留不动;安全组按出口 IP 限放 22025(本机出口 1.204.105.116 曾因未放行连不上,80/443 可达);本机旧记录~/.ssh/id_ed25519与 wb_deploy 脚本在当前设备不存在。 - 服务器安全加固(2026-08-27 完成):firewalld 已启用(放行 22025/80/443/3000/2222;cockpit/rpcbind 已停);fail2ban 保护 sshd(port=22025, maxretry5/bantime1h);监控脚本
/usr/local/bin/server-monitor.sh+ cron 每 10 分钟(调度在 xxcool 的 crontab:*/10 * * * * sudo /usr/local/bin/server-monitor.sh;日志/var/log/server-monitor.log,Bark 推送配/etc/server-monitor.conf的BARK_URL);告警去重终版(2026-09-11):状态目录/var/lib/server-monitor/——banned-ips.state(已提醒过的封禁 IP,只增不减 → 同一 IP 永不重复提醒)、ssh-src-ips.state(已提醒过的登录来源 IP,仅新 IP 首次登录才提醒)、ports.state(当前已告警的未登记端口,消失后清除)、ssh-brute.state(爆破告警状态机:attacking=本轮已提醒 /idle=已复位;攻击持续不刷屏,攻击停止静默复位,再犯视为新一波才重新提醒);完整审计仍在 fail2ban.log + journald 且已上报 admin 后台(脚本备份server-monitor.sh.bak.20260911);另有安全日志上报器/usr/local/bin/server-security-collector.sh(cron 每 5 分钟,xxcool crontab)→ POST 到127.0.0.1:10100/api/service/open/security/log/report,配置/etc/server-security.conf(INTERNAL_TOKEN)、状态/var/lib/server-security/last.ts;dnf-automatic 每天 06:00 自动安全补丁;SSH 密钥登录已部署(现用~/.ssh/xpcool_ed25519)、密码登录已禁。2026-09-11 加固:已关闭X11Forwarding(生效位置是 drop-in/etc/ssh/sshd_config.d/50-redhat.conf:17,主配置里那行是注释、改了无效;改前备份.bak.20260911,sshd -t预检 +sshd -T核对 +systemctl reload sshd不断连);nginx 遗留垃圾已清理(.code.xpcool.com.conf.swo、tool.xpcool.com.conf.download.0→ 移入/data/nginx/_junk_backup_20260911/,未直接删、可回滚)。nginx 配置目录约定:include /data/nginx/conf.d/*.conf;,故 conf.d 下非.conf后缀文件不会被加载。遗留待办:lighthouse账号(腾讯云自带 uid1000,NOPASSWD ALL)是否锁定待用户决策。坑:① 腾讯云安全组未放行 3000/2222/8081,Gitea 走 nginx 反代 80/443;② 改 sshd 前必须先sshd -t预检+备份(曾因脏行导致 SSH 断开);③ EPEL 源需腾讯云镜像(mirrors.cloud.tencent.com/epel)且 baseurl 必须手动写全;④ CentOS9 的 fail2ban 在 EPEL。⑤(2026-09-04 新坑)腾讯云改带宽若切计费模式会触发实例冷重启,重启后 firewalld 自定义端口规则曾丢失致 SSH 22025 失联(80/443 正常)——firewall-cmd 放行务必带--permanent,且实例冷重启后要复查 22025 放行。另:带宽 3M→5M 已升级(2026-09-04,实测 619KB/s 满速)。⑥(2026-09-11 溯源新坑)本机出口 IP1.204.105.116曾于 09-03 23:00 被自己的 fail2ban 封禁、09-04 23:00 才解封——这正是当时「SSH 22025 超时」的真因(当时误判为安全组未放行,绕了远路)。SSH 突然不通时,排查顺序应为:先fail2ban-client status sshd+grep Ban /var/log/fail2ban.log,再怀疑安全组。⑦(2026-09-11 体检结论)服务器未发现被入侵迹象:UID0 仅 root、无空密码账号、无异常 SUID/后门/劫持、无特权容器、系统目录近 30 天无改动;外网暴露面实测仅 22025/80/443(3000/2222/8081 等均被安全组挡住,firewalld 虽放行 3000/2222 但安全组是第二道闸)。 - 本地 pnpm 修复(2026-08-27 升级为 wrapper 方案):根因=本环境 MSYS 路径转换故障,把
/c/...参数转成E:\c\...(多E:\c\前缀)致 corepack shim 与 node 都找不到 pnpm.js。已建持久 wrapper:~/.workbuddy/binaries/node/bin/pnpm(内容:export NODE_OPTIONS=--experimental-sqlite; exec "<托管node.exe>" "C:/Users/ybtdevxxl/.workbuddy/binaries/node/workspace/node_modules/pnpm/bin/pnpm.cjs" "$@",关键=给 node 传 Windows 风格路径C:/...规避 MSYS 转换)。提交/构建前需PATH="~/.workbuddy/binaries/node/bin:$PATH"前置,pre-commit 钩子(lefthook oxlint/oxfmt/eslint/stylelint/checkType)即可正常运行;否则钩子崩 → 只能 --no-verify。已验证 pnpm 11.16.0 +pnpm exec oxlint1.79.0。
日常同步习惯(建议)
- 每次工作结束:在各改动项目
git add + commit,本工作空间同样提交(规则/日志变化时)。只 commit、不要 push(2026-09-01 用户明确:推送由用户自行完成,AI 无需代为 push,避免凭据交互失败)。 - 验证分工(2026-09-01 用户明确):AI 能做的验证(类型检查、构建、单元/二进制测试、自动化冒烟)照做;AI 不方便验证的部分(真实浏览器交互体验、视觉效果、下载弹窗等)直接交给用户手动验证,不要反复折腾自动化工具。
- 换设备开工前:先
git pull各仓库,保证规则与记录最新。
本机 Windows/PowerShell 工具链坑位(2026-09-10 实测,写脚本必看)
- PowerShell 工具不回显 stdout:exit code 正常但看不到输出;必须把结果
Out-File落盘,再用 Read 读取。Bash 里调powershell.exe会被安全策略拒绝。 [byte] -shl 8会溢出归零(结果仍是 byte 宽度)。字节拼 16 位整数必须先[int]转换,否则高位丢失(剪贴板/协议解析类代码的高频坑)。- 给 .ps1 加 BOM 绝不能用
Get-Content -Raw+Out-File:本机默认按 GBK 解码 UTF-8 文件,中文会被永久破坏且不可逆。正确做法是字节级前置EF BB BF([System.IO.File]::WriteAllBytes)。 - PATH 被裁剪:脚本里直接写
ping/netsh会报"无法识别",须用$env:SystemRoot\System32\xxx.exe绝对路径;且不要写& $exe args 2>$null | Out-String(会报"无法在管道中间运行文档"),改用$out = & $exe args再@($out) -join ' '。 - PowerShell 变量名不区分大小写:
$R与循环变量$r是同一个变量,会导致集合被静默覆盖。 - 后台监听的进程可能杀不掉(Stop-Process / taskkill 均无效),换端口重新起更省事。
- 防火墙规则按可执行文件路径匹配:一批 node.exe 规则指向已不存在的路径(失效);目前
C:\Users\xxl\AppData\Roaming\nvm\v23.0.0\node.exe有有效的 Public 档「TCP+UDP 任意端口」入站放行规则——需要做免提权的入站可达性测试时就用它监听。 - 测入站不要用 ping:Windows 默认拦 ICMPv6/ICMP 入站,必须用 TCP 端口测试。
- 国内测速:Cloudflare 端点不可用;用 Ookla 官方 CLI(
install.speedtest.net可直连下载)。 - 本机网络备注:家里的宽带是运营商级 NAT(CGNAT,第 2 跳 100.64.0.1),无公网 IPv4;但有公网 IPv6(
240e:338:263:3600::/64)。以太网被判定为 Public 网络档。 - 经
ssh.exe执行多行脚本会踩转义坑(2026-09-13 实测):把多行 here-string 直接当参数传给ssh.exe,远程 bash 解析到(等字符会报syntax error near unexpected token '(',而且报错前的行已经执行了,导致状态半途而废(证书只搬了一半)。可靠做法:本地写.sh文件(用-replace "rn","n"强制 LF +WriteAllTextUTF-8 无 BOM)→ **单独**scp上传 →ssh "chmod +x /tmp/x.sh && /tmp/x.sh"执行。注意echo | base64 -d | bash` 会被 PowerShell 工具安全策略直接拦截("Spawning a non-PowerShell shell")。 - 多源文件
scp不可靠(2026-09-13 实测):一次scp a b c d e host:/tmp/只落地了其中 2 个,且没有任何报错。每次只 scp 一个文件;脚本内用for+[ -f ]判断做幂等补齐,避免重复上传。 - 远程脚本一律写成幂等(
if [ -f ]判断后再mv -f),因为 SSH 调用可能被沙箱拦截/用户误拒而中断,重跑不能出错。
站点与容器清单(2026-09-13 核对)
服务器 193.112.118.168,容器均为
restart unless-stopped;除特别标注外只监听127.0.0.1,由宿主机 nginx 反代。
| 域名 | 容器 | 监听 | 说明 |
|---|---|---|---|
| admin.xpcool.com | —(静态 /data/www/) |
— | 管理后台前端 |
| 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 自托管 |
| 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 |
| status.xpcool.com | uptime-kuma |
127.0.0.1:3001 | 服务监控面板(2026-09-13 新增) |
| —(暂无域名) | bark |
0.0.0.0:8081 | Bark 推送服务端 |
| — | xpcool-mysql |
127.0.0.1:3306 | MySQL 8.0(库 service) |
Uptime Kuma(status.xpcool.com,2026-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 --memory 512m。服务器内存仅 3.7G 且 swap=0,必须限内存,避免 OOM 波及同机其他容器。 - v2 首次启动是「选择数据库」引导页(逻辑在
/app/server/setup-database.js,读data/db-config.json),选 SQLite 即可,之后进入创建管理员账号页。Uptime Kuma 没有找回密码入口,密码丢失只能改数据库/清 2FA,务必记牢。 - nginx 反代必须透传 WebSocket(
proxy_http_version 1.1+Upgrade/Connection头),否则面板无限重连、状态刷不出来。 - 证书:腾讯云免费 DV,CN/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比对,确认证书与私钥配套。 - 访问形态:
http:// → 301 → https://;公网实测ssl_verify=0、响应约 0.45s(2026-09-13)。 - nginx 配置模板见
.workbuddy/tmp/status.xpcool.com.conf。 - 监控的添加方式(2026-09-13 实测):Uptime Kuma 官方 REST API 不支持创建监控(只能读/暂停/恢复),只能走 Socket.IO(需面板账号密码,社区库
uptime-kuma-api)或直接写 SQLite。本项目采用后者:向monitor表 INSERT(字段均有默认值,只需给name/type/url/interval/retry_interval/maxretries/weight/description/accepted_statuscodes_json,user_id=1即xpcool),再docker restart uptime-kuma让服务端重新加载并开始探测。脚本:.workbuddy/tmp/add-monitors.sh(幂等,按 name 去重);改库前先备份/tmp/kuma.db.backup.<时间戳>。 - heartbeat.status 含义:
0=DOWN、1=UP、2=PENDING、3=MAINTENANCE;monitor_tls_info表会自动填充各站点证书信息(可用于证书到期监控)。 - 第一批监控(9 个,均 HTTP(s)、
accepted_statuscodes_json=["200-399"]、开启证书到期通知):站点 间隔 重试 权重 admin / service / git 60s 3 1000 file / read / tool / sub2api 120s 2 2000 code / status 300s 2 3000 service.xpcool.com单独放宽为["200-399","404"]:该后端是纯 POST 接口(遵循本项目"接口全 POST"规范),任何 GET 都 404;返回 404 说明 nginx + GoFrame 存活,后端进程真挂时 nginx 返回 502,仍会判 DOWN。- 待办:通知渠道尚未配置(建议接 Bark,可复用现有
bark容器及service.xpcool.com/bark/反代);「证书到期提前几天通知」需在面板设置里确认。