别再用那些老掉牙的教程了:Nginx 反代 + 免费证书自动续签,我踩过的坑都在这了

折腾过个人博客、小型电商站或者 API 网关的朋友,大概率都绕不开一个组合:Nginx 反向代理 + HTTPS。但真到自己动手时,问题就来了——证书怎么选?Let’s Encrypt 到底用 Certbot 还是 acme.sh?自动续签为什么总是静默失败?

笔者自己维护着几个日活不高但绝不能挂的小站,这些年把主流的几套方案翻来覆去试了个遍。今天不整虚的,直接上对比表和实操命令,把选型逻辑和踩坑经验一次性讲透。

一、选型背景:为什么不是“装上 Nginx 就完事”

💡 推荐阅读:别再手动传包了:从裸机到生产级容器,站长手把手教你Docker部署项目的正确姿势

很多人以为反向代理就是改个 proxy_pass,HTTPS 就是买个证书传上去。但现实是:

  • 商业 SSL 证书动辄几百上千一年,对个人站长是笔不小的开销;
  • 免费证书有效期只有 90 天,手动续签迟早会忘;
  • Nginx 配置里 ssl_certificate 路径写错一个字母,服务直接起不来;
  • 自动续签脚本跑在 cron 里,失败了你可能几周后才发现。

所以核心诉求很明确:零成本、全自动、高可靠。下面这张表是笔者对目前主流免费证书方案的横向对比,数据来自实际使用体验,不是官网抄的。

二、核心方案参数对比

💡 延伸阅读:Docker 容器又双叒叕起不来?别慌,这几个高频报错我帮你踩平了

对比维度 Certbot (官方) acme.sh 云厂商免费证书
价格 完全免费 完全免费 免费额度有限,超出收费
证书有效期 90 天 90 天 通常 90 天或 1 年
自动续签 内置 systemd timer,较省心 自带 cron 任务,极轻量 需手动重新申请并部署
依赖环境 Python 环境,体积较大 纯 Shell,无依赖 绑定云平台账号
适用场景 单机、新手友好 多域名、脚本化、容器环境 已重度使用某家云服务
优势 文档全,社区大,插件多 轻量、灵活、支持 DNS API 极广 控制台点选,零命令行
劣势 依赖 Python,某些系统装不上 需要一定 Shell 基础 换云厂商迁移麻烦,有锁定风险

看完表,结论其实已经比较清晰了。如果你只有一台服务器、一两个域名,Certbot 够用;但如果你像笔者一样,手里五六个域名、服务器环境五花八门,acme.sh 是更优解

三、方案 A 深度评测:Certbot 的舒适区与雷区

💡 深度技术指南:服务器半夜被挖矿、SSH 被暴力破解?聊聊我踩坑多年的 Linux 安全体检清单

3.1 安装与签发

以 Ubuntu/Debian 为例,安装极其简单:

sudo apt update
sudo apt install certbot python3-certbot-nginx

然后用 Nginx 插件一键签发并自动改配置:

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

Certbot 会自动帮你把 80 端口的验证做好,并写入 443 的 SSL 配置。对于新手来说,这步体验确实好。

3.2 自动续签机制

Certbot 安装时会自动创建一个 systemd timer,你可以这样检查:

systemctl list-timers | grep certbot

正常情况每天跑两次,续签前会做 dry-run。但笔者遇到过两个坑:

  • 坑一:服务器时区或时间不同步,导致续签窗口判断异常。建议开启 NTP 同步。
  • 坑二:Nginx 配置被后续手动改动,Certbot 的 --nginx 插件找不到对应 server 块,静默失败。这种情况日志在 /var/log/letsencrypt/,一定要定期看。

四、方案 B 深度评测:acme.sh 的灵活与强大

4.1 安装

一行命令搞定,不依赖 Python:

curl https://get.acme.sh | sh -s email=你的邮箱@example.com

安装后会自动加入 crontab,每天检查续签。

4.2 签发证书(以 DNS API 为例)

acme.sh 最强大的地方是支持几十家 DNS 服务商的 API,可以自动添加 TXT 记录完成验证,完全不需要开放 80 端口。以 Cloudflare 为例:

export CF_Token="你的Cloudflare API Token"
acme.sh --issue --dns dns_cf -d example.com -d *.example.com

注意 *.example.com 泛域名也一并签了,这在多子域场景下非常省事。

4.3 安装证书到 Nginx 并自动重载

关键一步,用 --install-cert 把证书放到指定路径,并设置重载命令:

acme.sh --install-cert -d example.com \
--key-file       /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.crt \
--reloadcmd      "nginx -s reload"

这样每次续签成功后,Nginx 会自动重载,全程无需人工干预。

4.4 Nginx 反向代理核心配置

证书就绪后,Nginx 配置才是重头戏。以下是一个经过生产验证的模板:

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

server {
    listen 443 ssl http2;
    server_name example.com www.example.com;

    ssl_certificate     /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         HIGH:!aNULL:!MD5;

    location / {
        proxy_pass http://127.0.0.1:8080;
        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;
    }
}

几个细节:X-Forwarded-Proto 必须加,否则后端应用可能误判协议导致重定向死循环;http2 在新版 Nginx 中建议改为 listen 443 ssl;http2 on;

五、最终选型建议

经过多轮实测,笔者的建议非常直接:

  • 如果你刚入门、只有一台服务器:用 Certbot,省心,出问题社区一搜就有答案。
  • 如果你有多个域名、多台机器、或者需要泛域名:无脑选 acme.sh,配合 DNS API,一次配置,永久自动。
  • 如果你已经在某家云厂商买了服务器:可以先用它的免费证书过渡,但务必做好迁移准备,别被锁定。

另外提醒一句:云服务器和域名是根基,别贪便宜选那种超售严重的小厂。笔者早年图便宜买过一家,结果续签时 DNS 解析半天不生效,折腾到凌晨。现在稳定用着几家主流云厂商的轻量服务器,配合 acme.sh,半年没碰过证书的事。

最后,自动续签不是配完就完事了。建议每月手动跑一次 acme.sh --cron --forcecertbot renew --dry-run,确认流程通畅。真正的自动化,是建立在可观测的基础上的。

相关技术专题与延伸阅读

滚动至顶部