实战:把个人博客挂上 HTTPS(证书、反代与回滚)

Article

实战:把个人博客挂上 HTTPS(证书、反代与回滚)

管理员效率工具56 阅读

实战:把个人博客挂上 HTTPS(证书、反代与回滚)

这篇文章按真实操作顺序写:假设你已经有一台云主机、域名解析到它、博客用 Docker Compose 跑在本机高位端口。目标不是再讲一遍概念,而是把「HTTP 能打开」推进到「HTTPS 稳定可访问,出事能退」。

开工前确认

先确认这几件事为真,再碰证书:

  1. http://你的域名/ 已能打开博客首页
  2. 前端/后端只监听 127.0.0.1 高位端口(例如 13000 / 18080
  3. 宿主机已安装 Nginx,且你有 sudo
  4. 域名的 A 记录已指向这台机器(裸域与 www 都要的话,两条都配)

用本机验证上游,避免被 DNS 缓存骗:

curl -I http://127.0.0.1:13000/
curl -I http://127.0.0.1:18080/api/health

上游不通,证书配得再漂亮也是 502。

证书怎么选

两条常见路:

  • Let's Encrypt(certbot):免费、适合个人站,要处理好续期
  • 商业证书:证书机构签发,常以 zip 提供 fullchain / privkey,适合已有备案与正式站点

无论哪种,证书 SAN 必须覆盖你真实使用的 Host。只签了 www、用户访问裸域,浏览器会报证书名不匹配。

商业证书常见落地:

sudo mkdir -p /etc/nginx/ssl/lostyouth.cn
sudo cp fullchain.pem /etc/nginx/ssl/lostyouth.cn/
sudo cp privkey.pem  /etc/nginx/ssl/lostyouth.cn/
sudo chmod 600 /etc/nginx/ssl/lostyouth.cn/privkey.pem

用 openssl 快速看链是否完整:

openssl s_client -connect 你的域名:443 -servername 你的域名 </dev/null 2>/dev/null | openssl x509 -noout -dates -subject

Nginx:80 跳转 + 443 反代

最小可用结构如下(按你的端口改):

server {
    listen 80;
    server_name lostyouth.cn www.lostyouth.cn;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name lostyouth.cn www.lostyouth.cn;

    ssl_certificate     /etc/nginx/ssl/lostyouth.cn/fullchain.pem;
    ssl_certificate_key /etc/nginx/ssl/lostyouth.cn/privkey.pem;

    client_max_body_size 20m;

    location /api/ {
        proxy_pass http://127.0.0.1:18080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /uploads/ {
        proxy_pass http://127.0.0.1:18080;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location / {
        proxy_pass http://127.0.0.1:13000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

改完务必:

sudo nginx -t && sudo systemctl reload nginx

-t 不过不要 reload。语法错硬重载,可能直接把入口打挂。

前端构建参数必须跟协议对齐

很多站点「证书绿了,页面还在请求 http:// API」。原因是前端构建时写入了旧的 SITE_PROTOCOL / DOMAIN。切 HTTPS 后要重建前端镜像或重新 build,而不是只 reload Nginx。

验证方式:

  1. 浏览器打开站点 → DevTools → Network
  2. 看 XHR/fetch 是否全是 https:// 同源 /api/...
  3. 出现 mixed content 警告就说明还有 http 资源

上线当天的验收清单

用无痕窗口跑一遍:

  1. http://域名 是否 301 到 https,且 Host 保持你输入的那个
  2. 首页、文章详情、归档正常
  3. 后台能登录、能发草稿、能上传封面(专门测大文件边界)
  4. www 与裸域(若都启用)都能打开且证书无警告
  5. curl -I https://域名/api/health 返回 200

出问题按层缩小:浏览器状态码 → Nginx error.log → curl 127.0.0.1:端口 → 容器日志。

回滚演练(建议真做一次)

在非高峰先演练:

  1. 备份当前 Nginx 站点配置:cp xxx.conf xxx.conf.bak.$(date +%F)
  2. 故意把 proxy_pass 改错,reload,确认出现 502
  3. 恢复 bak,再 reload,确认恢复

证书回滚同理:保留旧 pem 文件副本。商业证书替换前不要删旧文件;Let's Encrypt 则依赖 certbot 的版本目录。

数据层另说:MySQL 与 uploads 目录的备份不在本文展开,但 HTTPS 当天至少确认「容器重启丢不丢数据」——卷挂载错了,证书再正确也救不回内容。

常见翻车点

  • 安全组只开了 80,没开 443
  • 证书 SAN 缺 www 或裸域
  • 容器端口绑在 0.0.0.0,应用端口裸露公网
  • 只改了 Nginx,前端产物仍是 http
  • client_max_body_size 默认 1m,上传封面失败

小结

HTTPS 实战的关键路径是:上游本机可访问 → 证书覆盖正确 Host → Nginx 带齐转发头 → 前端按 https 重建 → 用清单验收 → 会回滚。把这六步做成习惯后,再加子域名站点(统计、其它项目)只是复制 server 块与换端口,而不是每次从零碰运气。

评论

暂无评论,来聊聊这篇文章吧。