证书 47 天就过期,还在手动续?聊聊我在 AWS 上的自动化方案

证书 47 天就过期,还在手动续?聊聊我在 AWS 上的自动化方案

上周帮朋友排查一个线上故障,折腾两小时最后发现------证书过期了。就这么简单又离谱的原因。客户打不开页面,浏览器直接甩一个 NET::ERR_CERT_DATE_INVALID,朋友还以为是 DNS 出了问题,查了半天。

更离谱的是,这种事以后会越来越频繁。CA/B Forum 去年通过了 Ballot SC-081,证书有效期会一路缩:398 天 → 200 天(2026.3)→ 100 天(2027.3)→ 47 天(2029.3)。到 2029 年,一个半月不续就挂。你管 5 台机器可能还能记住,管 20 台呢?靠人肉置巡?不现实。

今天分享一下我在亮马逊云科技上搞证书自动化的实践,踩过的坑一并说了。

先选路线:你的证书该谁管

在亚马逊云科技上搞 TLS,第一步是想清楚你属于哪种架构:

架构 方案 操心程度
ALB/CloudFront/API Gateway ACM 托管 完全不操心
EC2 上跑 Nginx/Apache Certbot + ACME 需要配一次
EKS Ingress cert-manager K8s 声明式

如果你的流量经过 ALB 或 CloudFront,直接用 AWS Certificate Manager(ACM),证书免费、自动续期、零配置。申请的时候加个 DNS 验证的 CNAME 记录,后面再也不用管了:

复制代码

aws acm request-certificate \ --domain-name "*.example.com" \ --validation-method DNS \ --region us-east-1

但现实是很多团队的服务直接跑在 EC2 上,TLS 终止在 Nginx。ACM 的证书没法导出私钥,装不到 Nginx 里。这种情况就得靠 ACME 协议 + Certbot 了。

Certbot 实战:三种模式怎么选

Nginx 插件模式(日常推荐)

Certbot 的 Nginx 插件会自动在你的 server block 里插入验证 location,验证完删掉,整个过程不中断服务:

复制代码

# 安装 sudo snap install certbot --classic # 一条命令搞定申请 sudo certbot certonly --nginx \ -d example.com \ -d www.example.com \ --email admin@example.com \ --agree-tos

装完看一眼证书状态:

复制代码

sudo certbot certificates # Certificate Name: example.com # Domains: example.com www.example.com # Expiry Date: 2026-09-15 (VALID: 89 days) # Certificate Path: /etc/letsencrypt/live/example.com/fullchain.pem # Private Key Path: /etc/letsencrypt/live/example.com/privkey.pem

Webroot 模式(不碠 Nginx 配置)

有些同事的 Nginx 配置比较复杂(比如用了大量 include 和自定义 map),不想让 Certbot 自动改配置文件。这时候用 Webroot 模式,自己加一段 location 就行:

复制代码

server { listen 80; server_name example.com; location /.well-known/acme-challenge/ { root /var/www/certbot; } }

然后跑:

复制代码

sudo certbot certonly --webroot \ -w /var/www/certbot \ -d example.com \ -d www.example.com \ --email admin@example.com \ --agree-tos

Standalone 模式(临时用用)

Certbot 自己起一个 Web 服务器来验证,但它得占 80 端口,意味着你得先停掉 Nginx。生产环境别用这个做续期,适合新机器初次部署还没装 Web 服务器的场景。

复制代码

sudo systemctl stop nginx sudo certbot certonly --standalone \ -d example.com \ --email admin@example.com \ --agree-tos sudo systemctl start nginx

自动续期的正确姿势

证书拿到了,怎么自动续?Certbot 的 renew 命令会扫描所有本地证书,距离过期 30 天内的自动续。

复制代码

# 先跑一遍 dry-run,确认流程没问题 sudo certbot renew --dry-run # 写 cron,每天凌晨 2:30 跑一次 echo "30 2 * * * root certbot renew --quiet --deploy-hook 'systemctl reload nginx'" \ | sudo tee /etc/cron.d/certbot-renew

踩坑重点--deploy-hook--post-hook 的区别。

  • --deploy-hook:只在续期成功时执行
  • --post-hook:不管有没有续期都执行

我之前用的 --post-hook,结果每天凌晨 cron 触发都会 reload Nginx,日志里全是无意义的 reload 记录。多张证书的时候更烦,一次 renew 跑完会 reload 好几次。改成 --deploy-hook 后世界清净了。

DigiCert ACME:企业级 OV/EV 也能自动化

Let's Encrypt 发的是 DV(域名验证)证书,免费好用。但有些企业内部合规要求 OV 或 EV 证书,显示公司名。好消息是 DigiCert 现在也支持 ACME 协议了,意味着付费证书也能走同样的自动化流程。

复制代码

# 注册 DigiCert ACME 账户(EAB 凭据从 DigiCert 管理后台获取) sudo certbot register \ --server https://acme.digicert.com/v2/acme/directory \ --eab-kid "YOUR_KEY_ID" \ --eab-hmac-key "YOUR_HMAC_KEY" \ --agree-tos --email admin@example.com # 申请证书 sudo certbot certonly --nginx \ --server https://acme.digicert.com/v2/acme/directory \ -d example.com

配好后续期流程跟 Let's Encrypt 完全一样,同一条 cron 通吃,不用额外改任何东西。

多台机器怎么管

单机 Certbot 配一次就好,但如果你有十几台 EC2 呢?一台台 SSH 过去配置不现实。三种思路:

思路一:流量收拢到 ALB。TLS 终止在负载均衡器,后端 EC2 只跑 HTTP。新服务强烈推荐这么干。

思路二:SSM 批量推送。用 AWS Systems Manager Run Command 一次搞定所有机器:

复制代码

aws ssm send-command \ --targets "Key=tag:Role,Values=webserver" \ --document-name "AWS-RunShellScript" \ --parameters 'commands=["snap install certbot --classic","certbot certonly --nginx -d $(hostname -f) --agree-tos -m admin@example.com -n"]'

思路三:EKS 用 cert-manager。K8s 环境下声明一个 ClusterIssuer,证书申请和续期全自动:

复制代码

apiVersion: cert-manager.io/v1 kind: ClusterIssuer metadata: name: letsencrypt-prod spec: acme: server: https://acme-v02.api.letsencrypt.org/directory email: admin@example.com privateKeySecretRef: name: letsencrypt-prod-key solvers: - http01: ingress: class: nginx

监控兜底:别光靠自动化

自动化做好了不代表可以完全放手。万一哪天 Let's Encrypt 服务端抽风、DNS 解析出了问题、安全组把 80 端口关了,续期就会失败。加一层监控兜底:

复制代码

import ssl, socket, datetime, boto3 def check_cert(domain): ctx = ssl.create_default_context() with ctx.wrap_socket(socket.socket(), server_hostname=domain) as s: s.settimeout(5) s.connect((domain, 443)) cert = s.getpeercert() expiry = datetime.datetime.strptime(cert['notAfter'], '%b %d %H:%M:%S %Y %Z') return (expiry - datetime.datetime.utcnow()).days def lambda_handler(event, context): for domain in ['example.com', 'api.example.com']: days = check_cert(domain) if days < 14: boto3.client('sns').publish( TopicArn='arn:aws:sns:us-east-1:123456789012:cert-alerts', Message=f'{domain} 证书还剩 {days} 天,请检查续期是否正常' )

用 EventBridge 每天触发一次这个 Lambda 就行。14 天阈值给了你两周的缓冲来人工干预。

我的建议

  1. 能上 ALB + ACM 的优先上,省心到不需要解释
  2. EC2 场景 Certbot + Nginx 插件 + deploy-hook,一次配好长期不管
  3. 企业证书走 DigiCert ACME,同一套自动化流程
  4. 不管哪种方案,都加上监控,14 天阈值告警
  5. 配完立刻跑 --dry-run,别等到真正续期那天才发现配错了

证书有效期缩短已经是定局,趁现在还有 200 天的缓冲期起紧把自动化做了。别等凌晨 2 点被告警叫醒才后悔。

相关推荐
zhangfeng11333 小时前
CI/CD 是软件开发中的两个核心实践,合起来指代一套自动化的软件交付流程
运维·ci/cd·自动化
弹简特6 小时前
【精通Postman接口测试】04-Postman的CLI命令+Jenkins和Newman+Allure+Jenkins自动化接口持续集成
自动化·jenkins·接口测试·postman
yyuuuzz6 小时前
aws注册过程中的常见问题梳理
运维·服务器·网络·云计算·github·aws
薛定谔的猫3691 天前
深入浅出:大语言模型 Agent 的工作原理与应用
人工智能·自动化·大模型·llm·ai agent
MATLAB代码顾问1 天前
AI Agent智能体开发实战:LangChain自动化工作流
人工智能·langchain·自动化
zhangfeng11331 天前
适合 5人以内小团队的Git 工作流 + Code Review + 自动化部署方案 FastAdmin +linunx服务器宝塔系统 外包项目 —
服务器·git·自动化·php·代码复审
zhangrelay1 天前
云课实践速通系列-基础篇汇总-必修-通识基础和专业基础-2026--工科--自动化、电气、机器人、测控等
linux·笔记·单片机·学习·ubuntu·机器人·自动化
yyuuuzz1 天前
aws注册过程中的常见注意事项
云计算·aws
缝艺智研社1 天前
誉财 YC - 10 + 双头全自动烫标机:服装商标烫印的高效智能之选
人工智能·自动化·新人首发·缝纫机·智能缝纫机