本文档介绍了如何使用 Lego(基于 Go 的 ACME 客户端)配合 AWS Route 53 DNS 验证,实现 Let’s Encrypt SSL 证书的自动申请与续签。
1. 安装 Lego (二进制版本)
Lego 提供了开箱即用的二进制文件,无需复杂的依赖,非常适合轻量级部署。
# 1. 前往 Release 页面下载最新版本的二进制包
# https://github.com/go-acme/lego/releases
wget https://github.com/go-acme/lego/releases/download/v5.5.2/lego_v5.5.2_linux_amd64.tar.gz
# 2. 解压并移动到工作目录
tar -zxvf lego_v5.5.2_linux_amd64.tar.gz
mkdir -p /root/letsencrypt
mv lego /root/letsencrypt/
(更多安装方式请参考 Lego 官方安装文档)
2. 配置 AWS IAM 权限
为了让 Lego 能够自动添加 DNS TXT 记录进行域名所有权验证,需要在 AWS 创建一个 IAM 用户,并赋予 Route 53 的操作权限。
- 登录 AWS 控制台,创建一个新的 IAM 用户,并生成 Access Key 和 Secret Access Key。
- 为该用户附加以下内联策略(最小权限原则):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": "route53:GetChange",
"Resource": "arn:aws:route53:::change/*"
},
{
"Effect": "Allow",
"Action": "route53:ListHostedZonesByName",
"Resource": "*"
},
{
"Effect": "Allow",
"Action": [
"route53:ListResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/YOUR_HOSTED_ZONE_ID"
]
},
{
"Effect": "Allow",
"Action": [
"route53:ChangeResourceRecordSets"
],
"Resource": [
"arn:aws:route53:::hostedzone/YOUR_HOSTED_ZONE_ID"
],
"Condition": {
"ForAllValues:StringEquals": {
"route53:ChangeResourceRecordSetsNormalizedRecordNames": [
"_acme-challenge.example.com",
"_acme-challenge.www.example.com"
],
"route53:ChangeResourceRecordSetsRecordTypes": [
"TXT"
]
}
}
}
]
}
安全建议:此策略遵循官方推荐的最小权限原则(Least Privilege)。请务必将
YOUR_HOSTED_ZONE_ID替换为您在 Route 53 中的实际 Hosted Zone ID。该策略通过Condition严格限制了 Lego 只能修改特定域名(example.com及其www子域)的 TXT 记录,防止意外或恶意篡改其他 DNS 记录。
3. 首次申请与自动化续签 (Cron)
首次手动申请
在配置定时任务前,建议先手动执行一次 run 命令来生成证书,确保 IAM 权限和网络连通性正常:
AWS_ACCESS_KEY_ID="您的AccessKey" \
AWS_SECRET_ACCESS_KEY="您的SecretKey" \
AWS_REGION="us-east-1" \
/root/letsencrypt/lego run \
--path /root/letsencrypt \
--email="your-email@example.com" \
--dns route53 \
--domains=example.com \
--domains=www.example.com
执行成功后,证书文件(.crt 和 .key)将保存在 /root/letsencrypt/certificates/ 目录下,您可以在 Nginx 中引用它们。
配置定时任务自动续签
使用 crontab -e 添加定时任务。
⚠️ 重要说明:在 Lego v5 版本中,
run命令已经合并了申请和续签的功能。 每天执行run命令时,Lego 会自动检查本地证书的有效期。如果距离过期时间大于 30 天,它会打印Skip renewal并安全退出;只有在距离过期不足 30 天时,才会真正向 Let’s Encrypt 发起续签请求。因此,在定时任务中直接使用run是完全安全的,不会触发 Let’s Encrypt 的频率限制。
# 每天 20:08 执行证书检查与续签。
# 使用 --deploy-hook 确保只有在证书真正成功续签时,才会执行 Nginx 重载,避免每天无效重载。
8 20 * * * AWS_ACCESS_KEY_ID="xxx" AWS_SECRET_ACCESS_KEY="xxx" AWS_REGION="us-east-1" /root/letsencrypt/lego run --path /root/letsencrypt --email="your-email@example.com" --dns route53 --domains=example.com --domains=www.example.com --deploy-hook="nginx -s reload"
留言