好久不见 – 2026 -《从“不安全”到小绿锁:一次HTTPS证书修复的折腾记》

缘起:那个让人焦虑的红色警告 ❌

“不是已经装了Let‘s Encrypt证书吗?”当时一脸困惑。是的,证书确实安装了,但Nginx就是不认,访问网站时浏览器依旧发出安全警告。

第一关:证书配置的“鬼打墙” 🔄

我们首先用Certbot获取了证书,看起来一切顺利:

sudo certbot --nginx -d jserfun.com -d www.jserfun.com

但重启Nginx后,问题来了——浏览器仍然显示不安全。第一反应是:“是不是证书没生效?”于是开始检查证书文件:

sudo ls -la /etc/letsencrypt/live/jserfun.com/
# 确实有证书文件啊!

检查Nginx配置,证书路径也对:

ssl_certificate /etc/letsencrypt/live/jserfun.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/jserfun.com/privkey.pem;

但就是不行。折腾了半个多小时, 发现我的 nginx 配置的 网站名jsefun.com 少了一个 r 字母

教训一:太马虎

第二关:Nginx的“倔脾气” 🐂

解决了证书链问题,新的错误又来了:

nginx: [emerg] unknown "connection_upgrade" variable

这个错误信息让我懵了。原来是在配置WebSocket支持时,用了一个Nginx不认识的变量。仔细检查配置,发现少了一个关键的 map 块:

# 缺少这个定义!
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

加上这个定义后,Nginx终于愿意启动了,但接着又来一个关于

关于启动细节的警告,这个警告其实是“假警报”——Let‘s Encrypt证书确实支持警告的细节,但需要额外的配置。最简单的解决方案?先禁用它!

教训二:Nginx的错误信息有时候很“委婉”,需要你像侦探一样解读。而且,不是所有警告都是致命的,有些可以暂时忽略。

第三关:PHP-FPM的“捉迷藏”游戏 🎭

解决了SSL问题,WordPress后台又打不开了。错误日志显示:

FastCGI sent in stderr: "Primary script unknown"

原来Nginx找不到PHP处理器。检查配置发现:

fastcgi_pass php:9000;  # Docker风格的配置

但在独立服务器上,应该是:

fastcgi_pass unix:/var/run/php/php-fpm.sock;

或者TCP连接:

fastcgi_pass 127.0.0.1:9000;

更糟的是,还有一个隐藏问题:PHP-FPM根本没在运行!需要手动启动:

sudo systemctl start php-fpm
sudo systemctl enable php-fpm

教训三:复制粘贴配置时要小心,特别是从Docker示例复制到物理服务器的场景。环境不同,配置也要相应调整。

第四关:权限的“俄罗斯套娃” 🇷🇺

终于,网站能打开了,但WordPress提示“无法创建目录”。一看权限,发现文件属于root用户,但Nginx以www-data用户运行

权限修复就像是俄罗斯套娃——层层深入:

  1. 目录需要可执行权限(x)
  2. 文件需要可读权限(r)
  3. 上传目录需要可写权限(w)

解决方案:

教训四:Linux权限系统既严谨又脆弱。记住这个文件权限规则!

第五关:防火墙的“沉默拒绝” 🧱

最诡异的问题是:本地访问正常,但外部无法访问。用了一小时才意识到——防火墙!

sudo ufw status
# 发现80和443端口没开

简单命令解决:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

但等等,还有云服务商的安全组!华为云、腾讯云、阿里云等都有自己的防火墙规则,需要在控制台额外配置。

教训五:现代服务器有多层防护——系统防火墙、云服务商安全组、Nginx配置。排查时要像剥洋葱一样,一层层检查。

那些我们踩过的“坑”和填过的“土” 🕳️

坑1:证书自动续期失败

Certbot配置了自动续期,但测试时失败:

sudo certbot renew --dry-run
# 失败原因:Nginx占用80端口,certbot无法验证

解决方案:使用webroot验证方式,或者暂时停止Nginx。

坑2:混合内容警告

即使有了HTTPS,浏览器还是显示“不安全”,因为页面中有HTTP资源。解决方法:

  • 使用相对协议://example.com/resource.jpg
  • 或者强制所有资源HTTPS

坑3:HTTP/2不工作

配置了listen 443 ssl http2;,但浏览器显示还是HTTP/1.1。原因是:Nginx版本太旧,或者SSL配置有问题。

技术收获 📚

1. 证书链的重要性

Let‘s Encrypt提供三个文件:

  • cert.pem:站点证书
  • chain.pem:中间证书
  • fullchain.pem:前两者合并

Nginx需要的是fullchain.pem,因为它需要完整的信任链。

2. 配置管理的艺术

学会了用代码管理配置:

3. 调试技巧

  • sudo nginx -t:测试配置语法
  • sudo tail -f /var/log/nginx/error.log:实时查看错误日志
  • curl -I https://domain.com:检查HTTP头
  • openssl s_client -connect domain.com:443:检查SSL握手

人生感悟 💭

1. 耐心是唯一捷径

在技术问题上,越是着急越容易出错。当我们卡在某个问题上超过30分钟时,最好的方法是:

  • 站起来走走
  • 喝杯水
  • 把问题从头再梳理一遍

2. 文档是最好的朋友

不管是Nginx官方文档、Certbot文档,还是Stack Overflow上的回答——总有人遇到过和你一样的问题。

3. 备份!备份!备份!

重要的事情说三遍。每次修改配置前:

# 创建带时间戳的备份
sudo cp 原文件 原文件.backup.$(date +%Y%m%d_%H%M%S)

最终检查清单 ✅

如果你的网站也需要HTTPS,按照这个清单检查:

  1. 证书路径正确(使用fullchain.pem
  2. Nginx配置语法正确(sudo nginx -t
  3. PHP-FPM正在运行(sudo systemctl status php-fpm
  4. 防火墙开放了443端口
  5. 云服务商安全组配置正确
  6. 证书自动续期配置完成
  7. 所有资源使用HTTPS
  8. HTTP强制跳转HTTPS
  9. 配置了HSTS头
  10. 做了完整备份

最后的最后 🎉

当浏览器终于显示那个绿色的小锁时,那种成就感简直难以言表。所有的报错、所有的调试、所有的“为什么还不工作”的呐喊,在那一刻都值得了。

技术就是这样——它不会因为你急就变得简单,但也不会因为复杂就不可攻克。每一次折腾都是一次学习,每一次解决都是对自己耐心的奖赏。

如果你也在HTTPS的路上挣扎,记住:你不是一个人在战斗。每个红锁背后,都有一个和你一样不肯放弃的技术人。

小锁虽小,安全事大。继续折腾,朋友!


后记:文章写完后,我又检查了一遍证书的自动续期配置,确保90天后不会再来一次这样的冒险。毕竟,好的系统应该能照顾好自己,而不是需要我时不时地“救火”。

如果你在HTTPS配置中也遇到了有趣的问题,欢迎在评论区分享——让我们一起少踩坑,多填坑!


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注