7.5.2 证书申请与自动续期实践
本节聚焦证书申请与自动续期的实操流程,覆盖域名准备、申请、部署、续期与故障排查,确保 HTTPS 证书持续可用。
原理草图:ACME 申请与续期流程#
证书类型与申请方式#
- 商业证书(DV/OV/EV):适合对品牌可信度要求较高的场景,通常需人工审核。
- ACME 证书(如 Let’s Encrypt):免费、自动化程度高。
- 自签名证书:仅用于内网测试或开发环境。
常见验证方式:
- HTTP-01:依赖 80 端口可访问。
- DNS-01:适合通配符证书或无法开放 80 端口场景。
- TLS-ALPN-01:使用 443 端口进行验证。
安装与准备(以 Ubuntu/CentOS 为例)#
安装 certbot#
# Ubuntu
sudo apt update
sudo apt install -y certbot
# CentOS/RHEL
sudo yum install -y epel-release
sudo yum install -y certbot
安装 acme.sh(可选)#
curl https://get.acme.sh | sh
source ~/.bashrc
域名与端口检查#
# 域名解析是否生效
dig +short example.com
# 80端口是否开放
sudo ss -lntp | grep ':80'
基于 certbot 的 HTTP-01 申请与部署示例#
Nginx 站点配置(预置校验目录)#
# /etc/nginx/conf.d/example.com.conf
server {
listen 80;
server_name example.com;
location /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
}
location / {
return 301 https://$host$request_uri;
}
}
# 创建校验目录
sudo mkdir -p /var/www/letsencrypt
sudo nginx -t && sudo systemctl reload nginx
申请证书#
sudo certbot certonly \
--webroot -w /var/www/letsencrypt \
-d example.com -d www.example.com \
--email admin@example.com --agree-tos --no-eff-email
证书生成路径:
- /etc/letsencrypt/live/example.com/fullchain.pem
- /etc/letsencrypt/live/example.com/privkey.pem
HTTPS 部署配置#
# /etc/nginx/conf.d/example.com-https.conf
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;
location / {
root /var/www/html;
index index.html;
}
}
sudo nginx -t
sudo systemctl reload nginx
命令解释#
certonly:仅申请证书,不修改 Nginx 配置。--webroot -w:指定校验文件写入目录。-d:绑定域名,可多次指定多域名。--agree-tos:自动同意服务条款。
基于 acme.sh 的 DNS-01 通配符示例(以 Cloudflare 为例)#
# 设置API密钥(示例变量名,按DNS服务商文档调整)
export CF_Token="your_cloudflare_token"
export CF_Account_ID="your_account_id"
# 申请通配符证书
acme.sh --issue --dns dns_cf -d example.com -d "*.example.com"
# 安装证书到指定路径
sudo acme.sh --install-cert -d example.com \
--key-file /etc/ssl/example.com/privkey.pem \
--fullchain-file /etc/ssl/example.com/fullchain.pem \
--reloadcmd "systemctl reload nginx"
自动续期实践#
certbot 定时任务(cron)#
# /etc/cron.d/certbot-renew
0 3 * * * root certbot renew --quiet --deploy-hook "systemctl reload nginx"
acme.sh 定时任务(systemd timer 示例)#
# /etc/systemd/system/acme-renew.service
[Unit]
Description=Acme.sh renew
[Service]
Type=oneshot
ExecStart=/root/.acme.sh/acme.sh --renew-all --quiet --reloadcmd "systemctl reload nginx"
# /etc/systemd/system/acme-renew.timer
[Unit]
Description=Acme.sh renew timer
[Timer]
OnCalendar=03:00
Persistent=true
[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now acme-renew.timer
续期脚本(仅更新时 reload)#
#!/bin/bash
# /usr/local/bin/renew_cert.sh
set -e
LOG=/var/log/renew_cert.log
certbot renew --quiet --deploy-hook "systemctl reload nginx" >> "$LOG" 2>&1
sudo chmod +x /usr/local/bin/renew_cert.sh
权限与安全管理#
# 证书私钥权限
sudo chmod 600 /etc/letsencrypt/live/example.com/privkey.pem
sudo chown root:root /etc/letsencrypt/live/example.com/privkey.pem
# 证书目录限制访问
sudo chmod 700 /etc/letsencrypt/live
常见问题与排查#
1. 验证失败(HTTP-01)#
# 检查校验文件是否可访问
curl -I http://example.com/.well-known/acme-challenge/test
# 查看 Nginx 访问日志
tail -n 50 /var/log/nginx/access.log
2. 证书未生效#
# 确认证书是否更新
openssl x509 -in /etc/letsencrypt/live/example.com/fullchain.pem -noout -dates
# 确认 Nginx 是否加载新证书
sudo nginx -T | grep -A2 ssl_certificate
3. 证书链不完整#
确保 Nginx 配置使用 fullchain.pem 而非 cert.pem:
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
练习#
- 使用
certbot申请一个包含example.com和www.example.com的证书,并部署到 Nginx。 - 改用
acme.sh申请*.example.com通配符证书,比较 DNS-01 与 HTTP-01 的差异。 - 编写一个续期脚本,在证书更新时记录日志并 reload Nginx。验证日志内容与更新时间。