1838 字
9 分钟

通过 Let's Encrypt 获取免费 SSL 证书的两种方法!

前言#

Let’s Encrypt 是目前免费 SSL 证书应用最广泛的一家,不仅免费而且证书也被众多机构认可。以前 Let’s Encrypt 的证书只支持顶级域名申请,不过现在已经支持通配符/泛域名 SSL 证书。泛域名证书比单域名证书方便多了,一次签发所有子域名通用,只需要担心续期问题。

今天我们来说下如何申请使用 Let’s Encrypt 泛域名 SSL 证书,这里提供两种方式:acme.sh 和 certbot。


一、通过 acme.sh 获取 Let’s Encrypt SSL 证书#

acme.sh 是一个纯 Shell 脚本编写的 ACME 客户端,支持多种验证方式,特别适合需要自动化 DNS 验证的场景。

安装#

Debian/Ubuntu 和 CentOS 8+ 都可以用同样的方式安装:

Terminal window
cd ~
curl https://get.acme.sh | sh

或者用 wget:

Terminal window
wget -O - https://get.acme.sh | sh

安装成功后,acme.sh 会被安装到用户目录下的 .acme.sh 目录中。

设置别名#

安装完成后需要创建一个 bash alias,或者直接加载配置:

Terminal window
alias acme.sh=~/.acme.sh/acme.sh

或:

Terminal window
source ~/.bashrc

设置 Let’s Encrypt 为默认 CA#

自 2022 年以后,acme.sh 默认将 CA 改为 ZeroSSL。如果希望使用 Let’s Encrypt,需要切换:

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

如果不设置这一步,申请证书时会卡在获取 EAB 授权那一步。

生成证书#

这里使用 DNS 自动验证方式验证域名所有权。acme.sh 目前支持 Cloudflare、DNSPod、CloudXNS、GoDaddy 以及 OVH 等数十种解析商的自动集成,请自行查看官方提供的 DNS API 文档

Cloudflare#

如果你的域名使用 Cloudflare 解析,设置 API Token:

Terminal window
export CF_Token="你的_Cloudflare_API_Token"
acme.sh --issue --dns dns_cf -d example.com -d *.example.com

DNSPod#

Terminal window
export DP_Id="你的_DNSPod_ID"
export DP_Key="你的_DNSPod_Key"
acme.sh --issue --dns dns_dp -d example.com -d *.example.com

手动 DNS 验证#

如果你的 DNS 提供商没有提供 API,可以使用手动验证方式。比如使用 Hurricane (dns.he.net):

Terminal window
export HE_Username="用户名"
export HE_Password="密码"
acme.sh --issue --dns dns_he -d example.com -d *.example.com

第一个 -d 后不能只写通配符域名 *.example.com,否则可能会出现签发的证书无法被信任的情况,一定要写个单域名。第二个 -d 后面可以写泛域名。

复制证书到指定位置#

正确的使用方法是使用 --installcert 命令,并将证书复制到指定目标位置:

Terminal window
acme.sh --installcert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/fullchain.cer \
--reloadcmd "systemctl reload nginx"

如果使用 service:

Terminal window
acme.sh --installcert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/fullchain.cer \
--reloadcmd "service nginx reload"

该命令会被自动记录,以后自动更新证书的时候也会自动执行该命令。

自动续期#

acme.sh 安装时会自动创建一个 cron 任务,每天检查证书是否需要续期。证书在 60 天以后会自动更新,无需任何操作。

如果需要手动触发续期:

Terminal window
acme.sh --renew -d example.com --force

Nginx 配置#

创建配置文件 /etc/nginx/conf.d/example.com.conf:

server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/fullchain.cer;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html;
}
}

测试配置并重启 Nginx:

Terminal window
nginx -t
systemctl reload nginx

注意事项#

  • Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer,而不是 /etc/nginx/ssl/example.com.cer,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误
  • 如果提示 acme.sh: command not found,需要执行 source ~/.bashrc 或注销并重新登录
  • 证书在 90 天以后会自动更新,无需任何操作

二、通过 certbot 获取 Let’s Encrypt SSL 证书#

Certbot 是 Let’s Encrypt 官方推荐的获取证书客户端,支持所有 Unix 内核的操作系统。

安装#

Debian/Ubuntu#

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

CentOS 8+#

Terminal window
sudo dnf install epel-release
sudo dnf install certbot python3-certbot-nginx

生成证书#

HTTP 验证(单域名证书)#

如果你的网站已经运行在 Nginx 上,可以使用 webroot 模式:

Terminal window
sudo certbot certonly --webroot -w /var/www/html -d example.com -d www.example.com

这个命令会在 /var/www/html 中创建 .well-known 文件夹,里面包含一些验证文件。certbot 会通过访问 example.com/.well-known/acme-challenge 来验证域名是否绑定的这个服务器。

Standalone 验证#

如果你的服务没有网站根目录,可以使用 standalone 模式。这个模式会自动启用服务器的 80 端口来验证域名的归属:

Terminal window
sudo certbot certonly --standalone -d example.com -d www.example.com

使用 standalone 模式时,如果有其他服务(如 nginx)占用了 80 端口,必须先停止这些服务,在证书生成完毕后再启用。

DNS 验证(泛域名证书)#

泛域名证书必须使用 DNS 验证方式:

Terminal window
sudo certbot certonly --manual --preferred-challenges=dns -d example.com -d *.example.com

执行这个命令后,certbot 会提示你添加一个 TXT 记录到你的 DNS 配置中。按照提示在 DNS 管理界面添加记录,然后按回车继续。

自动化 DNS 验证#

如果使用支持 API 的 DNS 提供商,可以自行搜索安装对应的 certbot 插件,来实现自动化 DNS 验证。例如使用 Cloudflare:

Terminal window
sudo apt install python3-certbot-dns-cloudflare

创建 credentials 文件 /etc/letsencrypt/secrets/certbot-cloudflare.ini

dns_cloudflare_api_token = 你的_Cloudflare_API_Token

设置文件权限:

Terminal window
sudo chmod 600 /etc/letsencrypt/secrets/certbot-cloudflare.ini

然后运行:

Terminal window
sudo certbot certonly --dns-cloudflare --dns-cloudflare-credentials /etc/letsencrypt/secrets/certbot-cloudflare.ini -d example.com -d *.example.com

证书位置#

证书生成完毕后,可以在 /etc/letsencrypt/live/example.com 目录下看到对应域名的文件夹,里面存放了证书文件:

  • fullchain.pem: 证书链(包含证书和中间证书)
  • privkey.pem: 私钥
  • cert.pem: 证书
  • chain.pem: 中间证书

Nginx 配置#

创建配置文件:

server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
location / {
root /var/www/html;
index index.html;
}
}

测试配置并重启 Nginx:

Terminal window
sudo nginx -t
sudo systemctl reload nginx

自动续期#

Let’s Encrypt 提供的证书只有 90 天的有效期。

从 certbot v0.19.0 开始,安装时会自动创建 systemd timer 和 cron job(通常在 /etc/cron.d/certbot),所以大多数情况下不需要手动添加续期任务。

检查自动续期是否正常工作:

Terminal window
sudo certbot renew --dry-run

这个命令会模拟续期过程,如果一切正常,说明自动续期已配置好。

特殊情况需要手动配置#

如果你的证书使用 standalone 模式生成,或者自动续期没有正常工作,则需要手动添加续期任务。

使用 standalone 模式时,如果有其他服务(如 nginx)占用了 80 端口,必须先停止这些服务,在证书生成完毕后再启用。

编辑 crontab:

Terminal window
sudo crontab -e

添加以下内容:

Terminal window
0 0,12 * * * certbot renew -q

这个设置会在每天凌晨 0 点和 12 点检查并续期证书。

如果是 standalone 模式,需要使用 pre/post hook:

Terminal window
15 2 * */2 * certbot renew --pre-hook "systemctl stop nginx" --post-hook "systemctl start nginx"

或者使用 service:

Terminal window
15 2 * */2 * certbot renew --pre-hook "service nginx stop" --post-hook "service nginx start"

--pre-hook 表示执行更新操作之前要做的事情,--post-hook 表示执行更新完成后要做的事情。


写在最后#

两种方式各有优势:

  • acme.sh: 轻量级,纯 Shell 实现,支持更多 DNS 提供商的自动化,适合需要自动化 DNS 验证的场景
  • certbot: 官方推荐,功能完善,支持自动配置 Nginx,文档完善,适合常规使用

选择哪种方式主要看你的具体需求。如果你需要支持更多的 DNS 提供商或者喜欢轻量级的解决方案,acme.sh 是不错的选择。如果你希望使用官方推荐的工具并享受自动配置的便利,certbot 会更适合。

无论选择哪种方式,都能帮你轻松获取免费的 SSL 证书,让你的网站拥抱 HTTPS。

支持与分享

如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!

赞助
通过 Let's Encrypt 获取免费 SSL 证书的两种方法!
https://blog.moewah.com/posts/164/
作者
GoWah
发布于
2025-01-14
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
GoWah
Hello, I'm GoWah.
分类
标签
站点统计
文章
160
分类
9
标签
350
总字数
301,106
运行时长
0
最后活动
0 天前

目录