SSL证书免费申请:Let's Encrypt配合Certbot自动续期,Nginx部署配置代码
SSL 证书免费申请最省事的路径:Let's Encrypt 签发,Certbot 自动续期,Nginx 加载证书并强制 HTTPS 跳转。下面按清单逐项给出命令、配置与排查顺序。
清单 1:动手前先确认这三项
域名解析已经指向本机。 在终端执行 dig example.com A +short、dig www.example.com A +short,返回的 IP 必须是你这台服务器的公网 IP。解析没生效就签发,验证请求会打到别处,报错多半是 Invalid response 或 Timeout during connect。
80 端口对外可用。 HTTP-01 验证默认走 80 端口,云厂商安全组、firewalld、ufw 三层都要放行。快速判断:curl -I http://example.com 返回 200/301/404 都算通,连接被拒就是被拦。如果 80 端口被封(部分机房要求备案后才开放),改用 DNS-01 验证,签发时加 --preferred-challenges dns,按提示在域名商处添加 TXT 记录。
Nginx 配置能回滚。 先把站点配置备份一份,例如 cp example.conf example.conf.bak。Certbot 的 nginx 插件会直接改写站点文件,改坏了得能一键还原。nginx -t 通过后再 systemctl reload nginx,不要用 restart。
清单 2:装 Certbot 的两种主流方式
方式 A,snap 安装,官方推荐,版本较新。
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot
certbot --version
snap 版自带定时续期单元,装完基本不用另配续期。CentOS/Rocky、Ubuntu 22.04 之后都适用。
方式 B,系统包管理器安装。
sudo apt update && sudo apt install certbot python3-certbot-nginx
sudo dnf install certbot python3-certbot-nginx
包管理器里的版本可能偏旧,但与系统集成更好,定时任务由 certbot.timer 提供。拿不准装哪个,打开 certbot.eff.org,选你的系统和 Web 服务器,页面会直接生成对应命令,照抄即可。
清单 3:签发证书,按场景选参数
场景一,机器上已有 Nginx 站点配置。 用 nginx 插件最省事,它会自动读 server_name、申请证书并写好 HTTPS 配置:
sudo certbot --nginx -d example.com -d www.example.com
首次运行要填邮箱(用于到期提醒)并同意条款。想跳过交互加 --non-interactive --agree-tos -m you@example.com。
场景二,Nginx 跑在容器里,或配置由其他工具生成。 用 webroot 模式,把验证文件落到站点根目录:
sudo certbot certonly --webroot -w /var/www/html -d example.com
先在 Nginx 里让 /.well-known/acme-challenge/ 可被公开访问,再执行签发。
签发成功后证书在 /etc/letsencrypt/live/example.com/ 下:fullchain.pem 给 ssl_certificate,privkey.pem 给 ssl_certificate_key。这两个路径是软链,续期后自动指向新文件,配置里直接写它们,不要把证书复制到别处。
清单 4:Nginx 的 HTTPS 配置要点
在站点 server 块里补齐下面几项:
listen 443 ssl http2;和listen [::]:443 ssl http2;ssl_certificate/ssl_certificate_key指向上面两个 pemssl_protocols TLSv1.2 TLSv1.3;,关掉 TLSv1/1.1ssl_ciphers HIGH:!aNULL:!MD5;,或直接用 Mozilla 的 intermediate 推荐值ssl_session_cache shared:SSL:10m;减少重复握手开销- 80 端口单独一个 server 块做跳转:
return 301 https://$host$request_uri; - 需要 OCSP stapling 时加
ssl_stapling on; ssl_stapling_verify on; ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem; - HSTS 先设短时长观察:
add_header Strict-Transport-Security "max-age=86400" always;确认站点没有 http 资源后再逐步调大
改完 nginx -t 验证语法,再 systemctl reload nginx。用 curl -I https://example.com 看状态码,用 openssl s_client -connect example.com:443 -servername example.com 看证书链是否完整。
清单 5:让续期真正自动跑起来
据 Let's Encrypt 官方文档,证书有效期约 90 天,续期窗口在到期前三十天内,所以必须自动化,否则某天早上站点会直接报证书过期。
- 确认定时器存在:
systemctl list-timers | grep -i certbot,snap 用户看snap.certbot.renew.timer,apt 用户看certbot.timer。没有就手动建 cron:0 3 * * * /usr/bin/certbot renew --quiet --deploy-hook "systemctl reload nginx" - 跑一次模拟续期:
sudo certbot renew --dry-run,走完整验证流程但不消耗真实额度,报错信息更容易定位 - 加部署钩子:Nginx 不会自动读新证书,续期后必须 reload。可在
/etc/letsencrypt/renewal/example.com.conf的[renewalparams]段加renew_hook = systemctl reload nginx,或用命令行的--deploy-hook。nginx 插件签发的证书通常已内置钩子,自己再确认一遍更稳妥 - 看日志:结果写在
/var/log/letsencrypt/letsencrypt.log,失败原因多半是 80 端口被改、DNS 记录被删、验证路径被重写规则拦掉
清单 6:出问题时的排查顺序
dig看解析,不对就先改 DNS 并等 TTL 过期curl -I http://域名/.well-known/acme-challenge/测试文件,404 是 root 路径写错,403 查目录权限nginx -t修语法错,别急着 reloadcertbot certificates看证书是否存在、到期时间和绑定域名journalctl -u nginx --since "10 min ago"看重载失败与读取权限问题- 浏览器控制台仍报混合内容,说明页面模板里还硬编码了 http 资源地址,改模板而不是改证书
证书目录默认权限已够 Nginx 读取,若报 permission denied,先查 /etc/letsencrypt/live 与 archive 的属主,别图省事 chmod 777。证书类型选 RSA 还是 ECDSA、是否购买商业证书做兜底,按自己业务的兼容要求定,费用以各平台页面为准。