21 KiB
21 KiB
2026-06-15 工作日志
Calibre-Web 电子书库部署
- Docker 部署
linuxserver/calibre-web:latest,端口 8083 - Caddy 反代
books.xybkwd.top(HTTPS 自动证书) - nav 导航页新增"电子书库"卡片(琥珀色书籍图标,book SVG)
- 所有卡片状态统一为"运行中"
- 要闻页面字体再次加大(移动端摘要 18px,标题 19px)
Gitea 仓库 ebook-library
- 通过 Gitea API 创建
fxy/ebook-library仓库(fxy token:513f4f51...) - 服务器
~/ebook-library/初始化,目录结构:scripts/、docs/、config/ - README.md + .gitignore 已推送
TIMELINE.md 修复
- TIMELINE.md 被 shell 转义弄乱,从 git 历史恢复原始内容后追加 Calibre-Web 条目
DNS 发现
books.xybkwd.topDNS 已解析到 43.163.225.30(可能是通配符或之前手动加的)- 腾讯云 DNS API 密钥未找到(Lucky 配置加密、服务器/本地全面搜索无果)
- 如需 API 密钥自动化 DNS,需冯总提供腾讯云 SecretId/SecretKey
用户偏好确认
- 冯总明确要淡化"beast"称呼,新仓库用
fxy组织,不使用 beast 命名
安全排查与加固
- 全面排查服务器安全状态:SSH 配置、防火墙、端口暴露、服务认证
- Lucky 已彻底删除(
/opt/lucky/+ Docker 残留全部清除) - 发现 Caddy basicauth 全部缺失(之前设置后被取消)
- 已恢复:gitea / dashboard / memo / nav / books 全部加上 basicauth(fxy / Qiyun2025!)
- 博客和 Vaultwarden 不加(博客公开,Vaultwarden 自身有登录)
- 验证通过:无密码返回 401,带密码返回 200
- 🔴 安全铁律已固化:严禁取消 basicauth,调试用 localhost 不改 Caddyfile
- 发现 Shadowsocks 服务在端口 31567(代理服务,正常)
- ufw 残留端口 16601(Lucky 残余)待清理,9001 待清理
DeepSeek 余额显示修复
- 问题:两个 cron 脚本都在写
/var/www/nav/data/balance.json,每小时整点互相覆盖inspiration-collector/tools/deepseek_balance.py— 扁平格式,JS 可读 ✅ai-chat/fetch_balance.py— API 原始格式(balance_infos嵌套),JS 解析失败 ❌
- 修复:删除
ai-chat/fetch_balance.py的 cron,只保留格式正确的那个 - 立即重跑脚本,余额恢复显示 ¥7.58
栖云个人服务部署方案 v2
- 生成完整方案文档(
栖云个人服务部署方案_v2.md),覆盖 8 个方向:- 全文搜索(Meilisearch)
- 书影音管理(Ryot + Calibre-Web)
- n8n 自动化(资源较重,建议后置)
- RSS Hub + Miniflux
- 图床(Lsky Pro)
- 自动化抓取(changedetection.io + Python 爬虫)
- 语音助手(极简 Web 方案)
- 微信读书同步(weread-exporter)
- 资源预算:全部部署内存 +950MB,磁盘 +1.35GB,当前可用 1.5G/45G,可行但偏紧
- 建议分三批推进,P0 优先:微信读书同步 + 图床 + 全文搜索
Memos 同步修复
- 问题:手机 App 同步不了,报"未能读取数据,格式不正确"
- 原因:Caddy basicauth 拦截了 Memos API 请求,App 无法通过 basicauth 认证
- 修复:memo.xybkwd.top 去掉 basicauth(Memos 自身有用户登录系统)
- 更新安全铁律:Memos 和 Vaultwarden 不加 basicauth,自身有认证
Memos API 调用踩坑记录(重要经验,已固化到 MEMORY.md)
- 协议:Memos 用 Connect RPC(POST + JSON),不是 RESTful GET
- 接口:
POST /memos.api.v1.MemoService/ListMemos - 字段名:时间字段是
createTime(不是createdTime/created_at),内容字段是content - 外网不可调:Caddy 反代
memo.xybkwd.top无法正常转发 RPC 请求,必须 SSH 到服务器走localhost:5230 - 认证:Bearer token,存在服务器
secrets/secrets.json的memos_token字段 - 本次踩坑:先用外网 REST 尝试(404)→ 再试 v1 路径(404)→ 最终通过 SSH localhost + Python requests 才成功提取数据
海康威视参观学习
- 冯总作为"90后四级副职培训班"学员(单位组织,浙大培训)参观海康威视总部
- 核心洞察:海康真正厉害的不是图像技术,而是3万SKU的生产排程和供应链管理能力
- 生成经历:v1(凭对话记忆,要点不全)→ 用户要求查 Memos → v3(基于真实 Memos,2101字)→ v4(修正身份为培训班学员,不限篇幅,4260字)
- 教训:生成课程/参观总结前,必须先从 Memos 提取真实记录,不能仅凭对话上下文编造;必须确认用户身份
- 已推送 Gitea:
inspiration-collector/ai-insights/daily/2026-06-15/ - 手动总结流程已固化到 MEMORY.md(Memos提取→本地生成→SCP上传→Git推送→附件发送)
灵感收集器标签功能改造
- 改造了
daily_digest.py和memos_client.py,让标签在 AI 分析中真正发挥作用 - 改动内容:
- AI 提示词新增标签说明段落(标签揭示场景、延续性、主题聚类)
- memo 按标签分组展示(同主题归在一起,方便 AI 融会贯通)
- frontmatter 自动记录当天出现的所有用户标签
- 跨日标签延续检测(如果今天和昨天共享某标签,提醒 AI 关注连续性)
- 新增
list_memos_by_tag()方法(支持按标签跨日检索) - 新增
aggregate_tags()+group_memos_by_tag()工具方法
- 篇幅规则更新:除"简要分析"限 2000 字外,其余不设上限
- 测试通过:8 条 memos,标签
90后四级副职培训班/浙江正确识别并传入 AI - 已推送 Gitea:commit
75586f1
灵感收集器标准话术库
- 盘点了灵感收集器全部功能(10 大模块:标签、每日分析、课程总结、周报、待办、新闻、余额、文库、运维、组合指令)
- 生成了标准话术库文档(
灵感收集器标准话术库.md),每句话术对应一个已实现的功能 - 覆盖 cron 自动运行和手动触发两种场景
自动任务文档
- 生成
docs/自动任务一览.md,记录服务器全部 14 条 cron + 6 个 systemd/Docker 服务 - 包含数据流向图,梳理各任务间的依赖关系
- 已推送 Gitea:commit
36a507e - 更新机制:每次 cron 变更必须同步更新该文件
每日要闻扩展栏目
- 新增 4 个栏目:政策速递、AI/量化前沿、市场行情、深度解读
- 新增 6 个 Python 脚本:
fetch_policy.py/summarize_policy.py— 政策 RSS + AI 摘要fetch_research.py/summarize_research.py— ArXiv AI/量化博客 RSS + AI 分类摘要fetch_market.py— A股指数(东方财富 API)+ 加密货币(CoinGecko API)deep_dive.py— 从要闻 Top1 选取,DeepSeek 生成 800-1200 字深度分析
- 新增 6 条 cron:政策/研究每6h抓取+摘要,市场每1h,深度解读每天22:35
- 改造 brief.html:新增市场行情顶栏(红涨绿跌)、sidebar 合并所有栏目、深度解读卡片置顶、5 分钟自动刷新
- 数据流:6 个 RSS 源 → 原始 JSON → AI 摘要 JSON → brief.html 并行加载
- 测试结果:政策15条、研究37条(3分类)、市场8条、深度解读1条(美伊停火分析)
- 自动任务文档更新至 v1.1
- 已推送 Gitea:commit
f31c741+0da3fc7
每日要闻 UI 修复(12:42~12:50)
问题 1:市场行情顶栏太丑
- 原版:单行水平滚动,A股和加密货币混在一起,排列混乱
- 修复:改为双行布局(A股一行、加密一行),每个指数/币种用 chip 卡片样式(带边框、圆角、背景),方向符号 ▲▼ 配色区分(红涨绿跌)
问题 2:所有分类栏目显示的都是深度解读
- 原因:深度解读卡片是独立的
deepDiveContainer,放在所有 cat-section 之外,但 sidebar 没有深度解读的独立 tab,只有第一个新闻分类 tab 是 active 的 - 修复:深度解读作为独立的 sidebar tab(排在第一位),点击只展示深度解读内容;其余 tab 各自对应自己的新闻分类。switchTab 改用
data-tab属性匹配
问题 3:ETH 行情"不见"(实际是 change_pct 显示重复)
- 根因:
fetch_market.py输出change_pct: "▲ 2.26%"(含方向符号),前端renderMarket又自行追加了一个chg-icon ▲,导致显示为▲ ▲ 2.26%,视觉上很乱 - 修复:后端
change_pct改为纯数值"2.26%",方向由is_up布尔值控制,前端统一渲染方向符号 - 附加:A股东方财富 API timeout 从 10s 提高到 15s,减少超时失败(东京服务器到国内 API 延迟不稳定)
- 已推送 Gitea:commit
e3a18a2+d86bede
经验固化:前后端数据契约
- 铁律:JSON 数据输出纯数值/布尔值,不包含渲染相关的装饰符号(▲▼ 箭头、$ 货币符号等尽量少)
- 方向/颜色/图标等展示逻辑统一由前端处理,避免前后端重复导致显示混乱
- A 股行情接口 timeout 需 ≥15s(东京→国内 API 链路不稳定)
新闻发布时间 pub_time 功能(14:30~14:50)
需求
- 冯总要求新闻卡片显示发布时间,判断新闻即时性
实现方案:后端回填 + 前端展示
- 后端:RSS 原始数据已有
published字段,但 AI 摘要脚本输出 JSON 时未保留 - 方案:AI 摘要输出后,用原始 RSS 的
published按标题精确匹配 + 前20字符模糊匹配回填pub_time - 时间格式:当天显示
HH:MM,非当天显示MM-DD HH:MM - 匹配率:news 96/102 (94%)、policy 8/15 (53%)、research 33/37 (89%)
- 依赖:
python3-dateutil的dateutil.parser.parse()解析各种 RSS 时间格式
修改文件
summarize_news.pyv2:新增build_time_lookup()+match_pub_time(),AI 提示要求保留原标题(匹配关键)summarize_policy.pyv2:同上summarize_research.pyv2:同上brief.html:新闻卡片 badge 行(.badge)改为 flex 布局,右侧显示.pub-timebackfill_pubtime.py:一次性脚本,给已有数据补填 pub_time- 已推送 Gitea:commit
eda0534
诸暨枫桥经验学习考察总结(15:34)
- 从 Memos 提取原始记录(1条 memo),用 DeepSeek API 生成课程分析(2148字/7分钟阅读)
- 内容:枫桥经验陈列馆参观 + 枫源村老书记骆根土座谈
- 关键概念已补充背景:枫桥经验历史、千万工程、四前工作法、四先四早、枫桥三贤等
- 已推送 Gitea:commit
8ab1b3c
🔴 模型选择铁律(14:47 冯总严令,18:48 补充界限)
- 智能体使用冯总积分时只准用 DeepSeek v4,任何步骤不得切换到其他模型
- 禁止智能体调用 GLM 模型(任何 GLM 系列均禁用)
- 补充:冯总自行购买的 API Key 由冯总自由切换,不在本禁止之列
手动日报触发 & 对比验证(16:01)
- 手动触发 daily_digest.py,生成今日日报(2916字/4条灵感),含海康+枫桥+数字基建
- 与课程总结(诸暨枫桥,2148字)对比:日报=思考输出(融会贯通),课程总结=知识存档(结构化笔记),互补关系
- 冯总满意两份文档,确认保留
冯总对写作体系的规划(16:07 确认)
- 日报:保持每天 22:30 cron 自动执行(当前培训期主要分析学习内容,后续加入工作事务)
- 课程总结/参观总结:手动触发,不设 cron(冯总自己决定什么时候生成)
- 写作体系方向:后续会开发多种写作模板,对文库、灵感库进行更多维度的发掘、梳理、分析和写作
- 本质上冯总在构建一个"个人知识管理 + 多维度写作输出"体系,灵感收集器是其中的核心引擎
待办推送修复(16:21)
- 问题:
extract_todos.py的 cron 每 30 分钟跑一次,但今天日报的待办没有推送到待办系统 - 根因(双重):
- AI 输出格式变了:从
[ ] checkbox变成1. **粗体**:描述,正则不匹配 - digest 文件路径变了:从
daily/YYYY-MM-DD_digest.md变成daily/YYYY-MM-DD/YYYY-MM-DD_digest_HHMMSS.md,脚本没递归子目录
- AI 输出格式变了:从
- 修复:
extract_todos.py升级为递归搜索 + 多格式匹配 + 模板标题过滤 - 已手动清理 4 条误推的模板标题(【今日输入】等)
- 测试结果:8 条待办提取成功,4 条有效待办推送到 API
- 已推送 Gitea:commit
1a3a211
第四小组政绩观学习研讨报告(17:00)
- 冯总要求以第四小组名义撰写《关于习近平总书记地方工作期间坚持正确政绩观生动实践》学习研讨报告
- 素材来源:Memos 全部培训记录(浙大3天课程)+ 诸暨枫桥经验学习总结 + 海康威视参观总结 + 权威资料(求是网、央广网、中工网等)
- 报告约4200字,四个部分:①政绩观核心要义 ②五个维度分析(战略定力/改革创新/为民情怀/担当作为/全面发展) ③第四小组学习收获 ④结语
- 贴合课程实际:枫桥经验、千万工程、八八战略、海康威视参观、科大讯飞参观、宇树科技讲座、数字浙江课程、章丰AI课程均有引用
- 已推送 Gitea:commit
79f166b - Word+PDF生成:python-docx + Word COM接口,符合公文格式(GB/T 9704-2012),标题和第四小组居中
Auto 模式 token 消耗排查(18:36~18:45)
- 冯总报告过去2小时 token 消耗巨大,要求排查
- 排查路径:DB 逐表查询 → trace 文件分析 → 会话消耗对比
- 我的错误:仅凭 sessions 表的 model 字段就下结论说"auto 选了大模型",没有核实实际调用的模型
- 事实(冯总去网页端对账后确认):1600+ 积分全烧在 GLM 5.0 Turbo 上,该模型当天 14:47 已被冯总明令禁止使用
- DB 里 session 标记为
deepseek-v4-flash,实际走的却是 GLM → sessions.model 字段不可信 - 教训已写入跨项目用户级 MEMORY.md:只信平台账单/API 日志,不信 DB 字段
- 冯总明确了模型使用界限:自己的 API Key 自由切换,我使用积分时只能用 DeepSeek
导航页重复登录修复 — Cookie Session Auth(19:00~19:05)
- 问题:Caddy basicauth 导致浏览器每 ~1 小时要求重新输入密码,尤其是移动端。用户每天登无数遍,痛点明显
- 根因:HTTP Basic Auth 依赖浏览器缓存凭据,移动浏览器缓存策略不稳定,且跨子域不共享凭据
- 方案:用 Python auth_proxy(port 9002)替换 Caddy basicauth,改用 Session Cookie(7 天过期,HttpOnly, SameSite=Lax)
- 架构:
- Caddy → auth_proxy:9002 → 验证 session cookie → 代理到实际后端或提供静态文件
- 无 cookie → 302 重定向到
auth.xybkwd.top/login?redirect=... - 登录后 Set-Cookie,7 天有效,跨子域共享
- 部署内容:
/home/ubuntu/auth_proxy.py— Python HTTPServer,bcrypt 验证密码,HMAC-SHA256 签名 token/etc/systemd/system/auth_proxy.service— systemd 服务,开机自启/etc/caddy/Caddyfile— 去掉所有 basicauth,改用reverse_proxy localhost:9002- 新增
auth.xybkwd.top→ 代理到 auth_proxy(登录页面,无额外认证)
- 测试结果:
- auth.xybkwd.top/login → 200,登录页面正常渲染
- nav.xybkwd.top(无 cookie)→ 302 跳转到 auth.xybkwd.top/login?redirect=...
- POST 登录(正确密码)→ 302 + Set-Cookie(7天)
- 带 cookie 访问 nav → 200,35KB index.html 正常加载
- 带 cookie 访问 dashboard → 200,48KB 仪表盘正常
- 带 cookie 访问 gitea → 200,13KB gitea 正常
- 安全性不降低:bcrypt 密码验证不变,cookie HttpOnly 防 XSS,HMAC-SHA256 签名防篡改
- 服务恢复正常:blog/vaultwarden/memo 不受影响(没有经过 auth_proxy)
auth_proxy 调试 — Cookie 跨子域修复(19:18~19:28)
- 现象:用户报告"登录以后直接不跳转了"——带 cookie 访问各子域仍被 302 回登录页
- 根因1(Cookie 跨子域失效):Set-Cookie 没有
Domain=.xybkwd.top,浏览器只为auth.xybkwd.top存 cookie,访问nav.xybkwd.top时不带 cookie- 修复:
cookie_val加Domain=.xybkwd.top;
- 修复:
- 根因2(语法错误导致服务崩溃):用 SSH heredoc 直接 patch Python 代码,导致
unterminated string literal,auth_proxy 反复 crash/重启- 修复:本地
py_compile验证语法 → SCP 上传,不再用 heredoc 写 Python
- 修复:本地
- 根因3(Set-Cookie 值带多余引号):
format()里用了中文引号"",导致sess="token..."而不是sess=token...,浏览器拒绝该 cookie- 修复:
sed -i去掉多余引号,验证Set-Cookie: sess=eyJ...(无引号)
- 修复:
- 根因4(多轮 hotfix 弄坏代码):多次 heredoc patch 叠加,最终
verify_token中SECRET_KEY引用错乱- 修复:本地重写完整
auth_proxy_v2.py,语法验证通过,一次性 SCP 覆盖
- 修复:本地重写完整
- 最终验证(curl 完整链路):
- POST
/login→ 302 +Set-Cookie: sess=...; Domain=.xybkwd.top; Max-Age=604800 - 带 cookie 访问
/→ 200,返回 35KB index.html - 带 cookie 访问
/api/todos→ 200,返回 JSON
- POST
- 经验:
- 🔴 禁止用 heredoc 写 Python 到服务器:SSH 转义规则复杂,极易引入不可见错误。正确流程:本地写 →
py_compile验证 → SCP 上传 → 重启 - Cookie 跨子域必须显式设
Domain=.example.com,否则浏览器按当前域名限制 Set-Cookie的 token 值不要加引号,RFC 6265 不允许- 调试代理服务:用
curl -D /tmp/hdr.txt -H "Cookie: sess=..." http://localhost:9002/...逐层验证
- 🔴 禁止用 heredoc 写 Python 到服务器:SSH 转义规则复杂,极易引入不可见错误。正确流程:本地写 →
- 已推送 Gitea:commit
pending
auth_proxy 事故 — Caddy 回滚(19:34~19:57)
事故经过
- 19:34 冯总报告:brief/dashboard/gitea 三服务同时"坏了"
- 根本原因:auth_proxy 替换了 Caddy 的反向代理层,但 auth_proxy 代理能力不完整
- Gitea Web/API 请求被 auth_proxy 拦截后无法正常工作
- dashboard /api/market-structure 等路径返回 404
- brief 的静态文件被 auth_proxy 的 serve_static 错误处理
回滚操作
- 恢复 Caddyfile:所有服务直接 reverse_proxy 到各自后端端口
- 保留 auth.xybkwd.top → localhost:9002(auth_proxy 仅作登录门户)
- 当前状态:所有服务 200 正常 ✅
basicauth 恢复失败
- 尝试恢复 basicauth 但 Caddy v2.11 的 hash 格式不兼容
- Caddy v2.11
basic_auth bcrypt要求的 hash 格式与caddy hash-password输出不一致 - $
$符号在 Caddyfile 中可能被解释为环境变量 - 临时方案:无 auth 开放访问(安全缺口待修复)
🔴 铁律:Git-First 部署原则(冯总19:57确认)
- 所有配置变更必须先 commit 到 git 仓库,再部署到生产环境
- 事故中幸亏能从 git 历史(commit 6c35f31)找回正确的 Caddyfile 版本,否则回滚将极为困难
- 本次教训:auth_proxy 调试过程中直接修改了 /etc/caddy/Caddyfile 和 /home/ubuntu/auth_proxy.py,未及时 git commit,这是一种危险的运维习惯
- 行动计划:未来任何生产环境变更,必须:
- 先在 git 仓库修改并 commit
- 再从 git 部署到生产
- 回滚时直接从 git checkout
- 更严格的版本:可以建立 /etc/caddy/ 的 git 仓库,与 Gitea 同步
已推送 Gitea
fxy/nav-pagecommit41f8ded— rollback Caddyfile 到直接代理beast/server-opscommit438245a— CHANGELOG v1.2.0 + 铁律记录
双认证方案上线(20:00~20:08)
- 架构:Caddy @authed cookie 匹配 + basic_auth bcrypt 兜底
- 有
sesscookie → 直接放行(7天免登录) - 无 cookie → basicauth 要求用户名密码
- auth.xybkwd.top/login → auth_proxy 签发 cookie(Domain=.xybkwd.top)
- 有
- 测试全部 7/7 通过 ✅
- 已推送 Gitea:
fxy/nav-pagecommita86991a
🏆 里程碑 V1 达成(20:33)
- 冯总确认:所有服务正常,认证架构按预期运行
- 认证架构定型:Cookie 免登录(7天)+ 统一登录门户 auth.xybkwd.top
- 完整快照已固化到 MEMORY.md 第 9 章「里程碑 V1」
- 核心文件均已 git commit,可秒级回滚
- Gitea 仓库最新 commit:
fxy/nav-page1a80249— Caddyfile(Cookie 路由 + 反代)beast/server-opsa6e85c6— auth_proxy + milestone_v1.md
Calibre-Web 配置踩坑(20:35~21:30)
问题1:上传后卡死、加载慢
- 根因:用宿主机
calibre 7.6的calibredb创建 metadata.db,版本与 Calibre-Web 容器内库不兼容 - 修复:清空书库,让 Calibre-Web 自己创建数据库
问题2:路径无效"DB Location is not Valid"
- 根因:
check_valid_db()函数要求 metadata.db 必须存在且有library_id表 - 修复:手动用 sqlite3 创建包含
library_id的空数据库
问题3:上传报错 "no such column: publishers.sort"
- 根因:手动创建的 metadata.db 表结构不完整,缺少
publishers.sort等列 - 修复:用
calibredb add创建完整规范的 metadata.db(397KB vs 手动82KB)
问题4:配置保存后仍 redirect 到 dbconfig
- 根因:settings 表中
config_calibre_uuid与 metadata.db 的library_id.uuid不匹配 - 修复:更新 settings.config_calibre_uuid 匹配 metadata.db.library_id.uuid
最终状态
- 中文界面 ✅ | 上传功能开启 ✅ | 站点标题"栖云书库" ✅
- 书库已有《道德经》1本,上传功能正常 ✅
- 数据库用 calibredb 创建,schema 完整,后续不再报错
- 关键经验:Calibre-Web 的 metadata.db 必须用 calibredb 或 Calibre-Web 自身创建,不能手动 sqlite3