缘起:那个让人焦虑的红色警告 ❌
“不是已经装了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用户运行
权限修复就像是俄罗斯套娃——层层深入:
- 目录需要可执行权限(x)
- 文件需要可读权限(r)
- 上传目录需要可写权限(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,按照这个清单检查:
- 证书路径正确(使用
fullchain.pem) - Nginx配置语法正确(
sudo nginx -t) - PHP-FPM正在运行(
sudo systemctl status php-fpm) - 防火墙开放了443端口
- 云服务商安全组配置正确
- 证书自动续期配置完成
- 所有资源使用HTTPS
- HTTP强制跳转HTTPS
- 配置了HSTS头
- 做了完整备份
最后的最后 🎉
当浏览器终于显示那个绿色的小锁时,那种成就感简直难以言表。所有的报错、所有的调试、所有的“为什么还不工作”的呐喊,在那一刻都值得了。
技术就是这样——它不会因为你急就变得简单,但也不会因为复杂就不可攻克。每一次折腾都是一次学习,每一次解决都是对自己耐心的奖赏。
如果你也在HTTPS的路上挣扎,记住:你不是一个人在战斗。每个红锁背后,都有一个和你一样不肯放弃的技术人。
小锁虽小,安全事大。继续折腾,朋友!
后记:文章写完后,我又检查了一遍证书的自动续期配置,确保90天后不会再来一次这样的冒险。毕竟,好的系统应该能照顾好自己,而不是需要我时不时地“救火”。
如果你在HTTPS配置中也遇到了有趣的问题,欢迎在评论区分享——让我们一起少踩坑,多填坑!
发表回复