WordPress 建站指南 HTTPS与SSL证书配置避坑指南
开宗明义:这篇文章解决4个具体问题——Nginx HTTPS 配置、Let's Encrypt 证书申请、 Certbot 自动续期、mixed content 混内容警告修复。不是泛泛而谈,是我在生产环境里踩过的真实坑。
---
为什么HTTPS对WordPress比以前更重要
2024年起Google已将HTTP页面标记为"不安全",更重要的是,现代浏览器对HTTP页面会屏蔽某些功能(比如地理位置、通知),而HTTP/2和HTTP/3都要求TLS。这意味着:不配置HTTPS,你的WordPress网站在速度和功能上就输了一截。
HTTP-01 验证需要 port 80,这个限制让很多人卡在第一步。我用的方案是 DNS-01,支持泛域名,但需要你的域名商支持APItoken。我在Cloudflare上配置了API token,整个申请过程不用开80端口,适合有特殊网络限制的用户。
现在的主流工具中,Certbot仍是官方推荐,acme.sh是更轻量的替代方案。Certbot在2026年4月刚更新到v5.5.0,支持最新的EAB(External Account Binding)要求;acme.sh则在2025年11月更新到3.1.2,功能稳定。两者我都用过,结论是:如果你用Ubuntu 24.04 + Nginx,直接用Certbot最省事。
---
踩坑1:Nginx配置HTTPS后WordPress后台变白屏
症状:配置好HTTPS后访问wp-admin,出现白屏或重定向循环。
根因:WordPress不知道网站已经HTTPS了,还在生成HTTP链接。
解决:在wp-config.php添加以下两行:
define('WP_HOME', 'https://' . $_SERVER['HTTP_HOST']);
define('WP_SITEURL', 'https://' . $_SERVER['HTTP_HOST']);
或者用wp-cli快速修复:
wp option update home 'https://yourdomain.com'
wp option update siteurl 'https://yourdomain.com'
这里我犯的错误是先修改Nginx配置,但忽略了WordPress本身的URL设置。正确的顺序是:先改WordPress配置,再配Nginx HTTPS。
---
踩坑2:Certbot申请证书时80端口被占用
**症状**:Failed to connect to port 80 错误,申请中断。
根因:Apache或另一个Nginx进程占用了80端口。
排查命令:
# 查看谁在监听80端口
sudo lsof -i :80
# 或者
sudo netstat -tlnp | grep :80
解决:停止占用进程后重试,或者用DNS-01绕过:
# 安装certbot插件
sudo apt install python3-certbot-dns-cloudflare
# 用Cloudflare DNS验证(不需要开80端口)
sudo certbot certonly --dns-cloudflare \
--dns-cloudflare-credentials /path/to/cloudflare.ini \
-d yourdomain.com -d "*.yourdomain.com"
我用的是Cloudflare,所以DNS验证方案对我最合适。但要注意:DNS-01验证后生成的泛域名证书,Cloudflare会自动配置,不需要手动改Nginx配置里的证书路径。
---
踩坑3:证书申请成功但浏览器显示"证书链不完整"
症状:用在线工具检测(如 SSLLabs),提示"Certificate chain incomplete"。
根因:Let's Encrypt使用RSpec协议颁发证书,但服务器只配置了Leaf Certificate,没有包含中间证书。
解决:在Nginx配置里指定完整证书链:
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
注意:fullchain.pem 包含完整证书链(leaf + intermediate),而 privkey.pem 是私钥。常见错误是用 cert.pem(只是leaf证书),导致链不完整。
SSLLabs检测结果从 C 升到 A 耗时约10分钟,因为证书已经申请成功,只是链配置错误的话修复后不需要重新申请,直接reload Nginx即可。
---
踩坑4:Mixed Content 混内容警告(最常见)
**症状**:浏览器控制台报错 Mixed Content: The page at 'https://...' was loaded over HTTPS, but requested an insecure resource 'http://...'。
根因:页面引用了HTTP资源(图片/CSS/JS),即使网站本身已配置HTTPS。
排查方法:打开Chrome开发者工具 → Console,搜索"Mixed Content",找到具体URL。
彻底解决方案:用wp-cli扫描并替换:
# 先备份数据库
wp db export backup.sql
# 扫描所有混内容URL
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com' --dry-run
# 确认无误后执行替换
wp search-replace 'http://yourdomain.com' 'https://yourdomain.com'
快速缓解方案:在Nginx配置里加入Strict-Transport-Security头,并让浏览器自动升级混内容:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header Content-Security-Policy "upgrade-insecure-requests" always;
upgrade-insecure-requests 指令告诉浏览器自动将页面内的HTTP资源请求升级为HTTPS,这是让老文章(数据库里大量旧HTTP链接)正常显示的最快方法,不需要逐个修复数据库。
---
踩坑5:Certbot自动续期失败
症状:证书到期了网站突然变红(不安全),查看systemd日志发现renew失败。
**根因**:Nginx reload需要平滑重启,直接restart会断连接;但有些人在reload时配置了require tty,导致cron下无法执行。
**正确的续期配置**:编辑 /etc/letsencrypt/renewal/yourdomain.com.conf,确保pre_hook和post_hook配置正确:
pre_hook = systemctl stop nginx
post_hook = systemctl start nginx
**不要用** reload 而要用 start/stop,因为Nginx的reload在某些配置下不会让新证书生效。
测试续期(不要等到过期才测):
# 模拟续期流程(不会真正申请)
sudo certbot renew --dry-run
# 如果测试通过,真正的续期会在后台自动运行
# 如果失败,systemd timer会通知你
我的教训:续期测试通过了,但真正到期时却失败了,因为测试时用的是standalone模式(停了Nginx),而真正续期时Nginx在运行导致端口冲突。所以确保pre_hook确实停了Nginx。
---
完整的Nginx HTTPS配置模板
以下是我在生产环境验证过的配置,适合Ubuntu 24.04 + Nginx 1.30:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/yourdomain.com/chain.pem;
# TLS版本控制(禁用TLS 1.0/1.1)
ssl_protocols TLSv1.2 TLSv1.3;
# 安全头
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
# CSP头:自动升级混内容
add_header Content-Security-Policy "upgrade-insecure-requests" always;
# OCSP Stapling
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# SSL session优化
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
root /var/www/html;
index index.php index.html;
client_max_body_size 100M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.well-known/acme-challenge/ {
allow all;
}
}
配置验证:sudo nginx -t 通过后再reload。
---
验证配置的工具
申请完成后不要只靠浏览器测试,用专业工具:
1. SSLLabs(https://www.ssllabs.com/ssltest/):输A即完美,输C说明链有问题
2. Mozilla SSL Config Generator(https://ssl-config.mozilla.org/):生成最新安全配置
3. CRT.sh(https://crt.sh/):查询证书是否正确申请
我用CRT.sh查到了Let's Encrypt的中间证书指纹,对比Nginx配置的 chain.pem,确认无误后才算完成整个配置。
---
总结:配置HTTPS的完整流程
1. 先改WordPress后台URL(wp-cli或后台设置)→ 避免白屏
2. 申请证书(Certbot standalone 或 DNS-01)→ 80端口问题这里解决
3. 配置Nginx HTTPS(fullchain.pem,TLS 1.2+1.3)→ 解决链不完整
4. 加CSP头(upgrade-insecure-requests)→ 快速解决混内容
5. 彻底替换数据库URL(wp-cli search-replace)→ 根治混内容
6. 测试续期(certbot renew --dry-run)→ 确保自动续期正常
这6步的顺序不能乱。WordPress配置优先于Nginx,证书申请优先于Nginx reload,DNS验证可以在绕过80端口限制的场景下使用。
---
你可能还关心:如果你用的是Docker方式部署WordPress,SSL配置会更复杂(需要docker-compose中的证书路径挂载),这个我踩过,下次单独写一篇Docker + HTTPS的配置方案。
👉 立即参与:https://platform.minimaxi.com/subscribe/token-plan?code=E5yur9NOub&source=link
🔗 Related Tech Articles
Deep dive into related technical topics: