返回笔记

如何获取免费的SSL证书

SSLHTTPSacme.shLet's Encryptnginx

为什么选 acme.sh + Let's Encrypt

自建站点需要 HTTPS,免费方案的主流选择是 acme.sh + Let's Encrypt。acme.sh 是一个零依赖的 Bash 脚本,实现了 ACME 协议,支持多 CA、自动续期、多种验证方式。

CA 对比

acme.sh 支持五个正式 CA:

CA有效期泛域名限制
Let's Encrypt90 天支持Rate Limit 较宽松
Buypass180 天不支持最多 5 个域名
ZeroSSL90 天支持有频率限制
SSL.com90 天收费免费版限制较多
Google Public CA90 天支持较新,社区资料少

选用 Let's Encrypt:社区资料最多,出问题容易搜到解决方案。

安装与配置

curl https://get.acme.sh | sh -s email=my@example.com

安装完成后会在 ~/.acme.sh/ 下创建目录,并自动添加 cron 任务,每天检测证书到期,到期前自动续期。

切换 CA:

acme.sh --set-default-ca --server letsencrypt

签发证书

HTTP 验证方式(需要域名已解析到服务器):

acme.sh --issue -d example.com -d www.example.com --nginx

--nginx 参数让 acme.sh 自动读取 nginx 配置完成验证,验证后恢复原状,不会修改现有配置。也可以使用 DNS 验证(适合泛域名或服务器不可达的场景):

acme.sh --issue -d example.com -d '*.example.com' --dns

安装证书

生成的证书在 ~/.acme.sh/ 下,不要直接让 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      "systemctl reload nginx"

--reloadcmd 在证书更新后自动重载 nginx,确保新证书生效。

nginx SSL 配置

server {
    listen 443 ssl;
    http2 on;
    server_name 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 ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;

    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 30m;

    # OCSP Stapling 加速 SSL 握手
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 valid=300s;

    # HSTS 强制 HTTPS
    add_header Strict-Transport-Security "max-age=63072000" always;
}

几个要点:

  • 只启用了 TLSv1.2 和 TLSv1.3,TLSv1.0/1.1 已于 2021 年废弃
  • ssl_ciphers 仅使用支持前向保密的 AEAD 套件
  • HSTS 头告诉浏览器在两年内(63072000 秒)始终使用 HTTPS,防止降级攻击

验证

SSL Labs 测试证书配置,目标 A+ 评级。