<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>实测手记</title>
    <link>https://585.ink/</link>
    <description>实测手记是一个技术实践记录站，记录建站、埋点、收录与多端合规的实测过程与踩坑，不吹数字。</description>
    <language>zh-CN</language>
    <lastBuildDate>Sat, 07 Nov 2026 15:18:37 GMT</lastBuildDate>
    <atom:link href="https://585.ink/feed.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>给静态站加全文搜索：从零搭 SQLite FTS5 索引</title>
      <link>https://585.ink/posts/04a7b4fe.html</link>
      <guid isPermaLink="true">https://585.ink/posts/04a7b4fe.html</guid>
      <description>站点文章过百后，前端 Fuse.js 全量加载 JSON 已让首屏明显变慢，遂改为构建期生成 SQLite FTS5 索引、后端只暴露一个查询接口。做法是写脚本遍历 Markdown 的 front matter 与正文，用 better-sqlite3 建表并插入，正文走 unicode61 分词、标题加权，同时把每篇的 slug 与摘要存成普通列便于回显。踩坑有三：一是中文分词默认按字切，长词检索命中差，改为在写入前做一次简单的二元切分并保留原串；二是索引文件随构建产物一起发布，被静态托管当普通文件下载，改用反向代理只允许 POST 查询；三是增量构建时表结构不一致导致查询报错，最终每次全量重建并加版本号校验。结论：百来篇文章索引不到 2MB，查询延迟稳定在毫秒级，比纯前端方案省下首屏体积。</description>
      <category>建站</category>
      <pubDate>Sat, 07 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用Caddy替换Nginx的静态站迁移实录</title>
      <link>https://585.ink/posts/8b8d62d2.html</link>
      <guid isPermaLink="true">https://585.ink/posts/8b8d62d2.html</guid>
      <description>把跑了两年的Nginx静态站迁到Caddy，起因是每次续签Let's Encrypt证书都要手动改配置并reload，而Caddy能自动完成签发与续期。做法：先用caddy adapt把现有server块转成Caddyfile作对照，再手写站点配置，用root指向静态目录、file_server开启目录服务、encode gzip zstd压缩、header设置缓存与安全头，最后加handle_errors自定义404。坑有两个：一是Caddy默认以caddy用户运行，站点目录权限不足导致403，改成目录组可读并给caddy组授权才通；二是原有的rewrite规则顺序在Caddy里被handle块重新排序，伪静态页面一度502，改用try_files等价写法后恢复。上线后证书自动续期正常，配置从80行降到30行，内存占用也更低。结论：纯静态站迁Caddy收益明显，但迁移前务必逐条核对rewrite与权限。</description>
      <category>部署</category>
      <pubDate>Fri, 06 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>给静态站加自托管评论：从踩坑到跑通</title>
      <link>https://585.ink/posts/d1670c09.html</link>
      <guid isPermaLink="true">https://585.ink/posts/d1670c09.html</guid>
      <description>本站一直是纯静态页，想加评论又不想引第三方脚本，于是选了自托管方案：在轻量服务器上用 Docker 起服务，配 SQLite 存储、反向代理转发到子域名，前端只嵌一段轻量脚本。坑主要三处：跨域与 Cookie 属性导致登录态丢失，需显式配置 SameSite 与允许来源；容器重启后数据没持久化，卷挂载漏写路径，评论丢了一次；邮件通知依赖外部 SMTP，被限流后改为延迟重试。最终把数据目录纳入备份脚本，评论可用且无外部依赖。</description>
      <category>建站</category>
      <pubDate>Thu, 05 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 systemd 定时任务清理博客缓存与日志</title>
      <link>https://585.ink/posts/018ab9ed.html</link>
      <guid isPermaLink="true">https://585.ink/posts/018ab9ed.html</guid>
      <description>站点跑在一台小内存 VPS 上，缓存目录和 journal 日志长期累积后会触发磁盘告警。我的做法是写一个清理脚本，用 find 按修改时间删除超过 14 天的缓存文件，再对 journalctl 做 vacuum-time 收缩，最后用 systemd timer 每天凌晨触发，而不是塞进 crontab，这样能拿到执行状态和日志。踩过的坑有两个：脚本里用了相对路径，timer 环境下工作目录不是预期值，改成绝对路径才生效；另外删除前没加 -xdev，差点跨挂载点清到备份盘。结论是定时任务要显式声明路径与挂载范围，并用 systemctl list-timers 验证触发情况。</description>
      <category>部署</category>
      <pubDate>Wed, 04 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把静态站迁到自建 VPS 的完整过程</title>
      <link>https://585.ink/posts/364b166d.html</link>
      <guid isPermaLink="true">https://585.ink/posts/364b166d.html</guid>
      <description>博客原先挂在托管平台上，为了能自己控制缓存和证书，我把它迁到一台自建 VPS。做法是：用 Caddy 反代静态目录并自动签发 Let's Encrypt 证书，用 rsync 从本地推送构建产物，systemd 单元保证 Caddy 开机自启，再用 cron 每天做一次增量备份。遇到的坑主要有三个：一是 DNS 切换后旧解析残留，导致证书签发校验失败，靠提前降低 TTL 并等待 TTL 过期解决；二是 rsync 默认权限导致静态文件不可读，加 --chmod 修正；三是防火墙只放行 80/443，忘了放行 SSH，差点把自己锁在外面。结论是自建部署可控性明显提升，但要把证书、备份、防火墙三件事当成日常运维项，不能一次配置完就不管。</description>
      <category>部署</category>
      <pubDate>Tue, 03 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把博客从VPS迁到对象存储的实操记录</title>
      <link>https://585.ink/posts/8b717e3a.html</link>
      <guid isPermaLink="true">https://585.ink/posts/8b717e3a.html</guid>
      <description>为了省掉每月维护VPS的精力，我把纯静态博客迁到对象存储加CDN。做法是先用rsync把构建产物同步到本地，再用对象存储的命令行工具上传，并给index.html和404.html设置正确的Content-Type与缓存头；自定义域名通过CDN回源到存储桶，并开启强制HTTPS。踩到的坑是默认缓存时间过长导致更新不生效，改成HTML短缓存、静态资源长缓存并配合文件名哈希后解决。结论是纯静态站点托管到对象存储更省心，但缓存策略和回源路径必须在上线前验证。</description>
      <category>部署</category>
      <pubDate>Mon, 02 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把个人站迁到自建Nginx的完整过程</title>
      <link>https://585.ink/posts/e7fd2e35.html</link>
      <guid isPermaLink="true">https://585.ink/posts/e7fd2e35.html</guid>
      <description>把跑在旧空间上的静态站迁到自建Nginx：先用rsync同步站点文件到新机器，证书用acme.sh签发并配置自动续期，Nginx开启gzip与长缓存，用location规则处理带hash的静态资源和404回退。配置完用curl -I和浏览器核对响应头，发现CSS被缓存导致样式错乱，改为对index.html禁用缓存后恢复正常。上线后保留旧站三天并加301跳转，确认无异常再下线。结论是自建部署可控性更好，但证书续期和缓存策略必须提前配好。</description>
      <category>部署</category>
      <pubDate>Sun, 01 Nov 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把博客从VPS迁到边缘函数的实操记录</title>
      <link>https://585.ink/posts/e4620f9b.html</link>
      <guid isPermaLink="true">https://585.ink/posts/e4620f9b.html</guid>
      <description>起因是VPS每月固定开销和单点故障：一次内核升级后Nginx起不来，站点停了四十分钟。做法是把纯静态的Hugo产物迁到边缘函数平台，构建放在CI里，push后自动生成并上传，域名走CNAME，证书由平台托管；动态部分只保留一个评论接口，用KV存数据，加简单限流。踩的坑有两个：一是边缘节点对缓存键处理不同，带查询参数的旧链接命中了错误版本，最后在函数里显式拼上路径与版本号；二是本地时区与构建机不一致，日期归档错位一天，改为构建时强制UTC。结论：静态站迁边缘后首字节明显变快，运维面缩小到只剩CI配置和评论接口，适合内容型站点，但涉及会话和写库的功能仍建议留在传统主机。</description>
      <category>部署</category>
      <pubDate>Sat, 31 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把静态站从VPS迁到对象存储加CDN的实操记录</title>
      <link>https://585.ink/posts/90db2dd8.html</link>
      <guid isPermaLink="true">https://585.ink/posts/90db2dd8.html</guid>
      <description>原站跑在一台2核2G的VPS上，Nginx直出静态文件，随着图片和归档增多，单机带宽和TLS握手成了瓶颈。做法是把构建产物上传到对象存储，开启静态网站托管，前面挂CDN并配置强制HTTPS与缓存规则：HTML设短缓存、带hash的静态资源设长缓存加immutable，回源走私有读加回源鉴权。踩的坑有三个：一是SPA路由的404回退要单独配置错误文档，否则刷新子路径全白屏；二是CDN默认不回传gzip，需在回源头里补Accept-Encoding，否则传输体积反而变大；三是证书签发后忘记清缓存，旧证书残留导致部分节点报错。结论：迁移后首屏耗时明显下降，源站压力几乎归零，但缓存规则和回退配置必须一次配到位，否则排查成本远高于省下的机器钱。</description>
      <category>部署</category>
      <pubDate>Fri, 30 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把博客从VPS迁到静态托管并加回滚脚本</title>
      <link>https://585.ink/posts/84ec4b09.html</link>
      <guid isPermaLink="true">https://585.ink/posts/84ec4b09.html</guid>
      <description>这次把跑了两年的VPS博客迁到静态托管：先用本地构建产出纯静态文件，再写部署脚本把产物同步到对象存储并刷新CDN缓存，同时保留上一版本目录做原子切换，出问题一条命令回滚。踩的坑有三个：一是构建时环境变量没注入导致统计脚本缺失，改成在CI里显式声明；二是相对路径在子目录页面失效，统一改成根路径加base配置；三是CDN缓存刷新有延迟，切换后旧页面仍可访问，加了版本前缀目录规避。结论是静态托管省掉了运行时运维，但构建与缓存的确定性必须靠脚本兜住，回滚能力比部署速度更重要。</description>
      <category>部署</category>
      <pubDate>Thu, 29 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代静态站并自动续期证书的实践</title>
      <link>https://585.ink/posts/48afe9fb.html</link>
      <guid isPermaLink="true">https://585.ink/posts/48afe9fb.html</guid>
      <description>把静态站从 Nginx 迁到 Caddy，用 Caddyfile 做反向代理与自动 HTTPS。做法：Caddyfile 里写站点域名，root 指向构建产物目录，file_server 开启，gzip 与 zstd 压缩，加 Cache-Control 长缓存并给 index.html 单独设 no-cache；上游若有 Node 服务用 reverse_proxy 指向 127.0.0.1 端口。坑一：Caddy 默认 80/443 需 root 或 setcap 授权，否则证书申请失败；坑二：防火墙未放行 80 端口导致 ACME 验证超时；坑三：缓存策略写错会让发版后用户仍看到旧页面。结论：Caddy 配置量小、证书自动续期省心，适合个人站，但缓存与端口放行必须显式检查。</description>
      <category>部署</category>
      <pubDate>Wed, 28 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把静态站迁到自建 VPS 的完整实录</title>
      <link>https://585.ink/posts/88645153.html</link>
      <guid isPermaLink="true">https://585.ink/posts/88645153.html</guid>
      <description>把跑在托管平台上的静态站迁到自建 VPS，用 Nginx 直接托管构建产物，systemd 管住构建脚本，Certbot 自动续期证书。踩的坑有三个：一是构建产物里的绝对路径在子目录部署时全部 404，改成相对路径后恢复；二是 Nginx 默认把目录当索引，关掉 autoindex 并补上 try_files 才避免目录泄露；三是证书首次签发时 80 端口被旧服务占着，先停服务再验证域名可达才成功。结论是自建 VPS 可控性明显更高，但必须自己盯证书到期和磁盘占用，我在 crontab 里加了续期检查和磁盘告警邮件，两周运行下来稳定。</description>
      <category>部署</category>
      <pubDate>Tue, 27 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>给静态站加一层自建边缘缓存实录</title>
      <link>https://585.ink/posts/1074751d.html</link>
      <guid isPermaLink="true">https://585.ink/posts/1074751d.html</guid>
      <description>站点迁到对象存储后回源延迟一直在两百毫秒上下，我在 VPS 上用 Nginx 加 proxy_cache 做了一层边缘缓存。做法是把静态资源按后缀分组设置不同的缓存时长，HTML 设短 TTL 并开启 stale-while-revalidate，再用 proxy_cache_lock 防止并发回源打穿。踩的坑有两个：一是默认 cache key 没带 Host 和 Accept-Encoding，导致不同域名和 gzip 版本互相串缓存；二是一开始把 5xx 也缓存了，源站故障时页面被钉死，后来用 proxy_cache_valid 只放行 200 和 301。实测命中率稳定在九成以上，回源延迟降到二十毫秒内，结论是静态站加自建缓存成本低、收益明确，但 key 设计和状态码白名单必须先想清楚。</description>
      <category>部署</category>
      <pubDate>Mon, 26 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>Caddy 反代加自动 HTTPS 的迁移实录</title>
      <link>https://585.ink/posts/4bddaa78.html</link>
      <guid isPermaLink="true">https://585.ink/posts/4bddaa78.html</guid>
      <description>把站点的 Nginx 反代换成了 Caddy，目标是省掉 certbot 续期脚本。做法：用 Caddyfile 写 reverse_proxy 到本机 127.0.0.1:8080，域名直接交给 Caddy 自动申请证书，保留原有 gzip 与缓存头配置。踩坑一：Caddy 默认占用 80/443，迁移时忘记先停 Nginx，启动直接报端口冲突；坑二：反代后后端取到的客户端 IP 全是 127.0.0.1，日志失真，加 trusted_proxies 并让后端读 X-Forwarded-For 才恢复；坑三：旧 Nginx 的 HSTS 头没同步，导致安全头缺失。结论：Caddy 配置量约为原 Nginx 的三分之一，证书续期零维护，反代场景值得迁移，但迁移前务必核对端口占用、真实 IP 传递与安全响应头三项。</description>
      <category>部署</category>
      <pubDate>Sun, 25 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代替换 Nginx 的实测记录</title>
      <link>https://585.ink/posts/eb84aa81.html</link>
      <guid isPermaLink="true">https://585.ink/posts/eb84aa81.html</guid>
      <description>站点原用 Nginx 反代，证书续期脚本偶尔失败导致 HTTPS 中断，于是换成 Caddy 并保留 Nginx 只做静态托管。做法：Caddy 监听 80/443 自动申请与续期证书，反代到本机 8080 的 Nginx；用 handle 与 reverse_proxy 配置，开启 encode gzip 与 HSTS，日志按天切割。坑一：Caddy 默认占用 80/443，先停 Nginx 再启动，否则绑定失败；坑二：真实 IP 需在反代头里透传，否则访问日志全是 127.0.0.1；坑三：证书签发要求域名解析已生效，新站先放行 DNS 再启动。结论：证书自动化省心，配置更短，静态仍交给 Nginx，故障面反而更小。</description>
      <category>部署</category>
      <pubDate>Sat, 24 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Docker 打包静态站并加健康检查的实践</title>
      <link>https://585.ink/posts/49061360.html</link>
      <guid isPermaLink="true">https://585.ink/posts/49061360.html</guid>
      <description>把 Hugo 生成的静态站放进多阶段 Docker 镜像，用 nginx:alpine 作运行时，构建阶段只保留 public 目录，镜像从 90MB 压到 23MB。容器加 HEALTHCHECK 定时请求 /healthz，返回 200 才算健康；同时用 docker compose 固定重启策略与只读根文件系统，日志走 json-file 并限制大小。踩到的坑有两个：一是 nginx 默认配置对带下划线的请求头返回 400，静态站本身无碍但健康检查路径要避开；二是只读根文件系统下 nginx 写 pid 和临时文件失败，需挂 tmpfs 到 /var/cache/nginx 与 /var/run。结论是这套组合在单机小站上足够稳，健康检查让反向代理能自动剔除异常实例，比单纯看容器 running 状态可靠得多。</description>
      <category>部署</category>
      <pubDate>Fri, 23 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 systemd 与 Nginx 加固个人站的实操记录</title>
      <link>https://585.ink/posts/9de66556.html</link>
      <guid isPermaLink="true">https://585.ink/posts/9de66556.html</guid>
      <description>把 585.ink 从裸跑 Node 进程改为 systemd 托管，前面挂 Nginx 反代，并加上日志轮转与健康检查。做法：用 systemd 单元文件声明运行用户、工作目录与 Restart=on-failure，限制内存与文件句柄；Nginx 只暴露 80/443，静态资源直出，动态请求转本地端口，并配置 proxy_set_header 传递真实 IP。踩坑：起初服务以 root 启动，日志权限错乱；启用 ProtectSystem 后应用无法写入上传目录，改为 ReadWritePaths 放行；日志未轮转导致磁盘一度告警，补上 journald 上限与 logrotate。结论：进程托管交给 systemd、边缘交给 Nginx，职责清晰，重启与排障都更可控。</description>
      <category>部署</category>
      <pubDate>Thu, 22 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代静态站并自动续期证书实录</title>
      <link>https://585.ink/posts/d9e5d091.html</link>
      <guid isPermaLink="true">https://585.ink/posts/d9e5d091.html</guid>
      <description>把 585.ink 从 Nginx 迁到 Caddy 后，静态站反代与证书续期一次跑通。做法：Caddyfile 里用 site 块写域名，root 指向站点目录，file_server 开启，再用 handle 给 /api 做反向代理到本机 127.0.0.1:8080；证书由 Caddy 内置 ACME 自动申请与续期，无需手写 cron。踩坑有三：一是 80/443 被旧 Nginx 占用导致 ACME 挑战失败，先停服务再启动即解；二是反代路径未加 strip 前缀，后端收到重复路径返回 404，改用 handle_path 解决；三是日志默认写系统日志，改成 output file 到独立目录便于排查。结论：静态站加少量反代用 Caddy 配置量更小，证书续期交给进程自身更省心，迁移前务必确认端口与 DNS 解析已生效。</description>
      <category>部署</category>
      <pubDate>Wed, 21 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把博客从VPS迁到家庭NAS的真实记录</title>
      <link>https://585.ink/posts/7659b200.html</link>
      <guid isPermaLink="true">https://585.ink/posts/7659b200.html</guid>
      <description>起因是VPS到期续费成本上升，我把静态博客迁到了家里的群晖NAS。做法：先用rsync把站点文件同步到NAS的web目录，再用Docker跑Caddy反向代理并自动签发证书，路由器上做80/443端口映射和DDNS解析。踩的坑有两个：一是运营商封了80端口，改用DNS-01挑战后证书才正常签发；二是NAS休眠导致首次访问超时，关掉硬盘休眠并加了一条健康检查定时任务后解决。结论：家庭宽带上行带宽足够个人博客，迁移后每月成本归零，但要接受动态IP和断电风险，建议再挂一个对象存储做每日备份。</description>
      <category>部署</category>
      <pubDate>Tue, 20 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代静态站并自签证书的实操记录</title>
      <link>https://585.ink/posts/78c528fa.html</link>
      <guid isPermaLink="true">https://585.ink/posts/78c528fa.html</guid>
      <description>把博客从 Nginx 迁到 Caddy，静态文件由 Caddy 直接托管，前面用反代指向本地 8080 端口的构建产物目录。做法是先用官方 apt 源装 Caddy，改写 Caddyfile：handle 静态路由、encode zstd gzip、file_server 并开启 browse 关闭目录列表，反代段用 reverse_proxy 127.0.0.1:8080 并加 health_uri 探活。内网测试域名没有公网解析，改用 tls internal 自签，把 Caddy 的根证书导入本机信任库，浏览器才不报警。踩的坑有两个：一是构建产物权限是 700，Caddy 以 caddy 用户运行读不到文件，改成 755 解决；二是 reload 后旧的 8080 进程残留导致 502，加了 systemd 依赖和探活才稳定。结论是 Caddy 配置量比 Nginx 少一半，自签场景够用，但上线公网前必须换真实证书并检查文件权限。</description>
      <category>部署</category>
      <pubDate>Mon, 19 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 替换 Nginx 的静态站部署实测</title>
      <link>https://585.ink/posts/ca480d39.html</link>
      <guid isPermaLink="true">https://585.ink/posts/ca480d39.html</guid>
      <description>把个人站从 Nginx 迁到 Caddy 2，主要是为了省掉手写 TLS 配置。做法：用 apt 装 Caddy，Caddyfile 只写域名、root 和 file_server 三行，反代 /api 用 reverse_proxy 指向本机端口；开启 encode gzip zstd 压缩，静态资源加 Cache-Control 长缓存并用 hash 文件名破缓存。踩坑两个：一是 Caddy 默认监听 80/443，和旧 Nginx 抢端口，先 systemctl stop nginx 再启动；二是 IPv6 AAAA 解析未同步，Let's Encrypt 签发时走 v6 超时，补上 AAAA 记录后自动续签正常。结论：配置量约为原 Nginx 的三分之一，证书自动续期免维护，适合单人维护的小站。</description>
      <category>部署</category>
      <pubDate>Sun, 18 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>给图片站加一层本地缓存代理，首屏快了一截</title>
      <link>https://585.ink/posts/ecaef2e5.html</link>
      <guid isPermaLink="true">https://585.ink/posts/ecaef2e5.html</guid>
      <description>站点部署在海外小机器上，图片直接走源站 CDN，国内访问首屏经常被图片拖住。这次在 Nginx 里加了一层本地缓存代理：用 proxy_cache_path 单独划出 2GB 磁盘缓存区，键按图片 URI 取，缓存 30 天，回源时带上 If-Modified-Since，并把 Cache-Control 的 s-maxage 作为有效期判断依据。坑有两个：一是源站返回 Vary: Accept-Encoding 导致缓存命中率极低，改成按 gzip 与 br 分键后命中率回升；二是缓存目录权限不对，worker 进程写不进去，日志里报 permission denied，chown 后正常。上线后图片第二次访问基本命中本地，首屏明显改善，源站带宽也降下来了。结论是：小站做图片代理，本地缓存比堆 CDN 套餐更划算，但要先把缓存键和权限这两件事弄对。</description>
      <category>建站</category>
      <pubDate>Sat, 17 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>给静态博客加全站搜索：Lunr 预构建索引实践</title>
      <link>https://585.ink/posts/1c7ab709.html</link>
      <guid isPermaLink="true">https://585.ink/posts/1c7ab709.html</guid>
      <description>站点文章过百后，翻归档找内容变得很烦，于是决定给纯静态博客加搜索。做法是在构建阶段用 Lunr.js 生成索引：写一个 Node 脚本遍历 content 目录下的 Markdown，用 gray-matter 取 front matter，用 remark 把正文转成纯文本，再截取前若干字符作为摘要，逐篇 add 进 Lunr 索引后序列化写入 public/search-index.json。前端搜索页只在用户聚焦输入框时才 fetch 这个文件并 lunr.Index.load，避免首屏白白下载几百 KB。踩的坑有三个：中文分词默认按空格切，整句进不去索引，改成对正文按单字和二元组合建 token；索引里带原始正文导致文件膨胀到近 1MB，压缩成仅标题加摘要后降到 120KB 左右；日期字段必须转成时间戳，否则按时间排序会错乱。结论是静态站完全能拥有可用的本地搜索，代价是每次构建多花两秒，换来零后端依赖和即时响应。</description>
      <category>建站</category>
      <pubDate>Fri, 16 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 给静态博客加一层自签 HTTPS 反代</title>
      <link>https://585.ink/posts/449cc66d.html</link>
      <guid isPermaLink="true">https://585.ink/posts/449cc66d.html</guid>
      <description>我的博客是 Hugo 生成的纯静态站，之前直接丢在 Nginx 后面跑 80 端口，后来想把内网预览和公网访问分开，就在同一台小机器上加了 Caddy 做反代。做法是让 Caddy 监听 443 并自动申请 Let's Encrypt 证书，静态文件继续由 Nginx 在 127.0.0.1:8080 提供，Caddy 只负责 TLS 终止和转发。踩的坑有两个：一是 Caddy 默认会去占用 80 端口做 ACME 挑战，和已有 Nginx 冲突，改成 tls 配置里指定 acme_ca 并让 Nginx 只监听 8080 才绕开；二是 Hugo 生成的目录权限是 755，Caddy 以非 root 运行读不到，chmod -R 755 后正常。结论是静态站加一层 Caddy 反代成本很低，证书续期也省心，但端口规划一定要提前想清楚。</description>
      <category>建站</category>
      <pubDate>Thu, 15 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把静态站迁到自建 Nginx 并开启 Brotli 的完整记录</title>
      <link>https://585.ink/posts/02d9a790.html</link>
      <guid isPermaLink="true">https://585.ink/posts/02d9a790.html</guid>
      <description>把跑在托管平台上的静态站迁到自建 Nginx，先在本地用同一份构建产物起容器验证，确认路由和 404 行为一致后再切 DNS。编译 Brotli 模块时踩了动态模块 ABI 不匹配的坑，改用与 Nginx 同源编译的源码重新生成模块才加载成功，并给 brotli_static 配了预压缩文件。缓存策略上对 HTML 设 no-cache、对带哈希的静态资源设一年 immutable，同时保留 gzip 作为回退。切换后首字节时间下降，Brotli 对文本类资源的压缩率优于 gzip。结论是自建部署可控性更强，但模块版本必须与 Nginx 严格对齐，预压缩和缓存头要一起设计。</description>
      <category>部署</category>
      <pubDate>Tue, 13 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 给静态站加自动 HTTPS 与 Brotli</title>
      <link>https://585.ink/posts/71a57801.html</link>
      <guid isPermaLink="true">https://585.ink/posts/71a57801.html</guid>
      <description>把 585.ink 从 Nginx 换到 Caddy，主要是想省掉 certbot 续期和 gzip 配置这两件烦事。做法：先备份原 Nginx 配置和证书目录，再用 Caddyfile 声明站点，encode 指令同时开 zstd、gzip 和 brotli，file_server 指向 /var/www/blog，并在 handle_errors 里自定义 404。坑有两个：一是 Caddy 默认用 80 端口做 ACME 挑战，而我的机器上旧 Nginx 还占着，必须停掉再启动，否则证书签发一直 pending；二是 brotli 对已经压缩过的图片没收益，反而多一层 CPU，我在 encode 后加了 match 排除图片后缀。结论：静态站迁 Caddy 后配置从 60 行降到 12 行，证书自动续期不用再管，Lighthouse 的文本压缩项直接满分，但动态反代场景仍需评估。</description>
      <category>建站</category>
      <pubDate>Mon, 12 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代替换 Nginx 后我的静态站省心了</title>
      <link>https://585.ink/posts/b2692e74.html</link>
      <guid isPermaLink="true">https://585.ink/posts/b2692e74.html</guid>
      <description>把跑了两年的 Nginx 静态站换成 Caddy，起因是每次加子域都要手写 server 块和证书路径。做法是装好 Caddy 后用一条 file_server 指令托管目录，反代部分用 reverse_proxy 指向本地 127.0.0.1 端口，证书交给它自动申请和续期。实际踩的坑有两个：一是 Caddy 默认监听 80/443，与旧 Nginx 冲突导致启动即报端口占用，先停掉 Nginx 再切换；二是前端用的 History 路由刷新 404，需要加 try_files 等价的 handle 配置把请求回落到 index.html。结论是配置量从几十行降到十来行，证书续期不再靠 cron，静态站和轻量反代场景完全够用，重写规则复杂的项目仍建议留在 Nginx。</description>
      <category>建站</category>
      <pubDate>Sun, 11 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>把静态站迁到自建 VPS 的完整踩坑记录</title>
      <link>https://585.ink/posts/4ce0b486.html</link>
      <guid isPermaLink="true">https://585.ink/posts/4ce0b486.html</guid>
      <description>把长期跑在托管平台的静态站迁到自建 VPS，用 Nginx 直接托管构建产物并在本机跑 certbot 签发证书。关键做法是先用 rsync 把 dist 同步到 /var/www，再单独建站点配置，避免改动默认 server 块；证书续期改为 systemd timer 触发，并在 Nginx 配置里预留 /.well-known/acme-challenge 路径，防止 webroot 校验被重定向规则拦截。踩的坑主要有三个：一是 DNS 的 A 记录改完后本地仍命中旧 IP，排查后确认是递归缓存未过期，用公共解析器验证才定位；二是权限问题，rsync 后文件属主是 root，Nginx worker 读不到，加 --chown 参数解决；三是忘记放行 80 端口，certbot 一直超时。结论是自建托管成本可控、可控性更强，但每次变更都要把 DNS、权限、防火墙三件事逐条过一遍，做成检查清单最省心。</description>
      <category>部署</category>
      <pubDate>Sat, 10 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>给静态博客加上全文搜索：从 40MB 索引压到 1.2MB</title>
      <link>https://585.ink/posts/6dbdea79.html</link>
      <guid isPermaLink="true">https://585.ink/posts/6dbdea79.html</guid>
      <description>我的博客用纯静态生成器部署在对象存储上，文章涨到 300 多篇后站内搜索成了刚需。第一版直接用构建脚本把全部正文塞进一个 JSON，产物 40MB，首屏要等好几秒，移动端基本不可用。这次改成构建期切词建倒排索引：用 jieba 对标题和正文分词，过滤停用词，记录每篇文章的词频与位置偏移，同时写入文章元数据表。查询时先匹配词项再按词频和标题命中加权排序，只返回摘要片段和锚点，不加载全文。索引分片成若干小文件按需拉取，gzip 后 1.2MB。踩的坑是中文分词对英文技术词会切碎，加了英文词表保护；另外停用词过滤太狠会漏召回，把高频虚词保留但降权。结论是静态站也能有可用的全文搜索，关键是索引体积和首屏加载的权衡。</description>
      <category>建站</category>
      <pubDate>Fri, 09 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>用 Caddy 反代换掉 Nginx 的实测记录</title>
      <link>https://585.ink/posts/91e0831e.html</link>
      <guid isPermaLink="true">https://585.ink/posts/91e0831e.html</guid>
      <description>站点原先跑 Nginx + 手动 certbot 续期，证书偶尔因 cron 失败导致过期。这次换成 Caddy 2，做法是：用 apt 装 Caddy，Caddyfile 里只写域名、root 和 file_server，TLS 由 Caddy 自动申请与续期，再用 reverse_proxy 把 /api 转发到本地 Node 服务。迁移时踩了两个坑：一是 80 端口被旧 Nginx 占用导致 ACME 挑战失败，必须先停服务并确认防火墙放行；二是 Caddy 默认以 caddy 用户运行，静态目录权限不足会返回 403，需 chown 或调整目录权限。切换后证书续期无需人工干预，配置文件从近百行缩到十几行，负载相近。结论：个人站点用 Caddy 替代 Nginx 能显著降低证书维护成本，但端口占用与文件权限必须在切换前处理好。</description>
      <category>建站</category>
      <pubDate>Thu, 08 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>三个站共用一套：GitHub SSH 推送即部署</title>
      <link>https://585.ink/posts/e69f53d9.html</link>
      <guid isPermaLink="true">https://585.ink/posts/e69f53d9.html</guid>
      <description>主站 HTTPS 推送被挡后改用 SSH 协议，各静态仓库注册仓库级 runner，git push 即触发部署。联系只留一个邮箱，反馈与其他需求统一跳到 antucao.com，入口不发散。</description>
      <category>部署</category>
      <pubDate>Tue, 06 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>备案主体换到个体工商户经营性后，广告才敢挂</title>
      <link>https://585.ink/posts/c5ad71b4.html</link>
      <guid isPermaLink="true">https://585.ink/posts/c5ad71b4.html</guid>
      <description>个人非经营性备案不得从事有偿服务（292 号令第十一条，无证经营罚则 10 万–100 万），那类主体下不能挂广告。本站主体已迁至个体工商户经营性、备案号下发后，才恢复广告与优惠券位投放；站名与备注文案要同主体一致，否则驳回。</description>
      <category>合规</category>
      <pubDate>Sun, 04 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>收录从 0 条起步：我的观测与回填台账</title>
      <link>https://585.ink/posts/783f89e5.html</link>
      <guid isPermaLink="true">https://585.ink/posts/783f89e5.html</guid>
      <description>不吹「服务了多少团队」。用一份 observation.json 跟踪每个页面提交与收录状态，sitemap 提交后人工逐条核对，收录状态回写台账，空着就标 unknown，不编造数字。</description>
      <category>收录</category>
      <pubDate>Fri, 02 Oct 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>事件表先登记，再埋点：我对账不掉数的做法</title>
      <link>https://585.ink/posts/7ed906d7.html</link>
      <guid isPermaLink="true">https://585.ink/posts/7ed906d7.html</guid>
      <description>把要埋的事件先登记成口径表（conversion.json），页面埋点与脚本各填一处。构建期脚本双向对账：登记了没埋的、埋了没登记的都列出来，数字才信得过。</description>
      <category>埋点</category>
      <pubDate>Wed, 30 Sep 2026 00:00:00 GMT</pubDate>
    </item>
    <item>
      <title>一份 JSON 加一个脚本，搭出零依赖静态站</title>
      <link>https://585.ink/posts/6e88b73c.html</link>
      <guid isPermaLink="true">https://585.ink/posts/6e88b73c.html</guid>
      <description>这个站没有打包器、没有 node_modules。一份 HTML 模板 + 一份数据 JSON + 一个 Node 预渲染脚本，跑一次就把内容渲染成静态 HTML。禁用 JS 也能读到全文，部署到任意静态托管即可。</description>
      <category>建站</category>
      <pubDate>Mon, 28 Sep 2026 00:00:00 GMT</pubDate>
    </item>
  </channel>
</rss>

