给个人博客 blog.alleria.cn 部署 HTTPS 并固化成可复用部署 skill(2026-09-04)

今天做了什么

今天给 blog.alleria.cn 接入了 HTTPS。我的博客是 Node.js Express + Markdown 搭的个人系统,域名就挂在简历上,之前一直裸跑 HTTP,浏览器地址栏那个不安全标记既难看又影响访客信任。本以为跑一条 certbot 命令就完事,结果顺带翻出一处藏了很久的 nginx 配置笔误,最后还把整套流程做成了可以反复用的 skill。

这次操作对我而言不只是一个“上证书”的动作,更是一次把运维能力写进作品集的练习——做了十年前端,我越来越认同全栈不只是写业务代码,能独立把服务安全、稳定地跑起来才是真本事。

技术细节与踩坑

签发本身很顺。certbot 的 nginx 插件一条命令完成签发和反向代理改写:

sudo certbot --nginx -d blog.alleria.cn --redirect -n --agree-tos

它签出 ECDSA 证书(落在 /etc/letsencrypt/live/blog.alleria.cn/,有效期 89 天),自动给站点配置加上 443 ssl 监听,并把 80 端口跳 301 到 443。续期交给定时器:certbot.timer 每天跑两次 renew,--nginx 插件自带 deploy hook,续期成功后自动 reload nginx。同机的 getoffer.alleria.cn 用的就是同一套机制,互不冲突。

真正的坑在后面。翻配置时我发现,之前用 heredoc 写 nginx 时,把变量 $proxy_add_x_forwarded_for 误写成了 $proxy_add_x_forward_for(少了 ed)。这个变量没定义,导致磁盘上的配置执行 nginx -t 会直接报 [emerg]。可巧的是,当时正在跑的 nginx 用的是内存里的旧配置,外网一直正常,所以这个雷一直没爆——直到某次重启才会炸。

我重连服务器做的第一件事就是 sudo nginx -t,确认输出 syntax is ok / test is successful;再 sudo nginx -s reload,看到 signal process started,才算真正把 on-disk 与 running 两处配置都修正并对齐。

还有几个小细节值得记一笔:certbot 默认 ssl 配置走 options-ssl-nginx.conf 的 include,而另一站点手写 ssl_ciphers,两者并存无冲突;ssl_stapling 在没有 OCSP URL 时会有一条无害 warn,按用户要求保持开启、不折腾。

方法论沉淀

这次最实在的收获是关于配置漂移的教训:内存态和磁盘态不一致,是运维里最隐蔽的雷,平时风平浪静,一重启就原形毕露。我的做法是把“改完配置必 nginx -t、随即 reload 验证”写进固定清单,不再只靠外网自查。

更进一步,我把整个 HTTPS 部署流程固化成了 https-cert-setup skill,放在 user 级 skills 目录,并打成了可发布包。它的结构是:

  • SKILL.md:六步工作流——收集参数(域名 / SSH / Web 服务器类型 / 301 跳转 / HTTP2 / dry-run)→ 环境检查 → 签发 → 验证 → 续期确认 → 汇报。
  • references/pitfalls.md:本次实战的全部踩坑,包括 root 禁登、expect 与 MOTD 输出截断、certbot 报错对照表、必须先 nginx -t 再 reload、PM2 端口错配导致 502 的陷阱。
  • scripts/ssh_run.exp:一个不依赖 sshpass 的密码 SSH 模板,输出落服务器 /tmp 文件防止回显截断。

设计上遵循最小改动原则:不主动加 Stapling 等额外项,无害 warn 不折腾——这条来自用户反馈,也成了 skill 的默认行为。

结尾

从一条 certbot 命令,到一处配置漂移排查,再到一套可复用工作流,这次经历把“部署运维”也实打实地攒进了我的求职作品集。对个人开发者来说,能端到端把服务安全地跑起来,本身就是一个很有说服力的工程能力证明。

更多复盘见 blog.alleria.cn。