缘起
上一篇记录了博客系统的搭建:iStoreOS 小主机上,Hugo + Gitea + 在线编辑器的骨架立起来了。但那时的它还只是一个「能用的毛坯」:发布靠手动构建再拷贝到云服务器,编辑器只能写新文章,改已发布的内容要 SSH 上去改文件,图片更是没有像样的通道。
这篇记录的是接下来两天发生的事:它被升级成了一套全自动出版系统——而且这一次,大部分活不是我干的,是 AI 干的。
现在的流水线长什么样
写作(三选一)
① 在线编辑器 edit.blog.is-i7.cn (公网,Basic Auth)
② Gitea 网页 :3000
③ 直接改 pi 上的源码后 git push
↓ push
Gitea 钩子 deploy-blog
↓ hugo 构建(约 210ms)
↓ rsync --delete 走 WireGuard 隧道 → 云服务器
预览站(:8888) 和 is-i7.cn 同步更新
从点「发布」到文章上线,全程不到 10 秒。构建在树莓派级别的小主机上完成,云端只做静态托管——3GB 内存的小盒子跑得毫不费力。
编辑器的进化
最初的编辑器只有标题、标签、正文三个框,发布按标题生成文件名——意味着改一个已发布的标题就会创建一篇新文章,而旧文永远无法修改。
升级后的编辑器:
- 文章侧栏:列出全部已发布文章,点开即载入编辑器,发布按钮自动变为「更新原文」——保留原文件路径、保留原始发布日期、自动携带版本号
- 图片按钮:选图自动上传图床,光标处插入直链,编辑器预览里也能直接看到
- 断线续编:刷新页面会恢复「正在编辑哪篇」的状态,不会误当新文章发出去
这些功能上线前经过了一轮「编辑器链路测试」——你没看错,博客里那些名字朴素的测试文章(《编辑器测试》《编辑器链路测试》《测试在线编辑文稿》)就是那个阶段诞生的。它们是 AI 用真实浏览器一轮轮点出来的:新建、发布、从列表加载、修改、再发布、验证线上更新、删除。测试全绿之后,它们作为脚手架被撤下了——但 git 历史里永远留着,算是这段调试期的化石。
图床:一次 PHP 到 Rust 的改道
图片最初跟博客仓库放在一起,后来决定独立成图床。第一站是 PHP 写的 EasyImages——功能全,但 253MB 的容器镜像总觉得笨重。后来换成了 Rust 的 dufs:
镜像体积 253MB → 3MB
运行内存 ~50MB → ~10MB
功能上做减法:不需要相册、不需要评论,只要「上传 + 直链 + 权限」。dufs 的权限模型刚好合适——匿名只读(博客外链直接可用),账号可写(上传走反代注入凭据,前端零暴露)。网页拖拽、命令行 curl -T、编辑器插图三条路全通。
顺带一提,pi 在国内拉不动 Docker Hub,镜像是在云服务器上拉好、打包、走 WireGuard 隧道送回来的——3MB 的包,隧道两秒送达。
隧道:这一切的地基
上面反复出现的「WireGuard 隧道」值得单独一节。家里的小主机在 NAT 后面,云服务器有公网 IP,于是组了一张星型小网:
云服务器 (中心节点 100.72.0.1, UDP)
│
┌────────────┼────────────┬──────────┐
小主机 Mac 笔记本 RackNerd 家里其他设备
100.72.0.2 100.72.0.3 100.72.0.5 .4
博客发布走它,图床流量走它,SSH 运维走它。Mac 上的隧道做成了系统服务:开机自启、掉线 20 秒内自动拉起——在公司、在咖啡馆,ssh pi 永远直连。
踩坑实录(本篇技术含量最高的部分)
- 闭合代码栅栏不能带语言标注。一次批量「修复」把
```结尾也标成了```plain,Markdown 规范里带标注的栅栏只能开启代码块——于是整篇文章被吞进一个巨型代码块。修复用状态机:代码块开启状态下遇到的栅栏一律还原为裸栅栏。 - OpenWrt 的 ssh 是 dropbear 的 dbclient,不认
-F配置文件,密钥格式也和 OpenSSH 不通用。部署脚本突然连不上,装openssh-client才解决。 - Docker bind mount 会遮住镜像内容。挂载空目录到
/app/web,应用代码直接消失,nginx 只剩 403。修法:从镜像临时容器里docker cp出完整应用再挂载。 - dufs 的上传权限是两层:账号规则给
rw之外,还得加全局--allow-upload;匿名规则写@/:ro,那个ro少个o都不行。 pkill -f会自杀:模式串出现在自己的命令行里,把自己的 shell 也杀了,后面的清理命令全没执行。- nginx reload 有切换瞬间:旧 worker 还在用旧配置,紧跟着的请求会撞上 403/405,几秒后再测就好——不是每次报错都是真的报错。
每一个坑现在都沉淀在服务器文档里,下次不管是人还是 AI 接手,都不用再踩一遍。
关于「AI 的劳动」
这套系统升级期间,AI 通过 SSH 和浏览器完成了大部分实操:改配置、写钩子、调前端、起容器、压测权限、修被改坏的 markdown、最后还把测试文章清理下线。人负责做决定——换 Rust、删测试帖、标题改成什么——AI 负责把决定变成现实,并把过程写进文档。
所以这篇也算一份工作记录:编辑部现在有两个人(类),一个出主意,一个出手。下一篇不知道谁执笔,但流水线已经不挑作者了。
落日余晖,记录折腾与思考——现在也记录一点人机协作。