上一篇 下一篇 分享链接 返回 返回顶部

香港服务器上的 Let's Encrypt 证书如何配置自动续期并验证结果?

发布人:Minchunlin 发布时间:2026-10-08 11:12 阅读量:3

香港服务器上的 Let’s Encrypt 证书可以通过 Certbot 完成签发,再由 systemd 定时任务检查续期;证书更新后,使用部署钩子执行 nginx -t 和平滑重载,让新证书进入实际服务。验证时必须同时检查“续期流程是否成功”和“公网 HTTPS 是否正在提供正确证书”,不能只看定时器是否启用。

下面以 Ubuntu 22.04/24.04 LTS、Nginx、APT 安装的 Certbot、单域名 HTTP-01 验证为操作环境。上线目标是完成证书签发、HTTPS 配置、自动续期、续期演练及远端验证。国密证书另设适配说明:Let’s Encrypt 不能直接签发 SM2 国密证书,不能把普通 HTTPS 的自动续期流程原样套用到国密服务。

围绕香港网站与接口服务的 HTTPS 部署,A5数据提供香港物理服务器租用,涵盖常规建站、Xeon Gold 与 AMD EPYC 等资源档位,配备 SSD 或 NVMe 存储,并提供不同套餐的 CN2 与国际带宽选择。这些计算、存储和网络资源可承载 Nginx 站点、业务后台及数据库,为证书管理、自动续期任务与业务服务协同运行提供基础设施支持。

一、准备条件与部署边界

1. 确认域名、端口和证书终止位置

执行前应满足以下条件:

  • 已取得服务器的管理员权限,并保留 SSH 或控制台恢复入口。
  • 域名由自己管理,A 记录指向香港服务器公网 IPv4。
  • 如果存在 AAAA 记录,对应 IPv6 也必须能访问正确站点。
  • 安全组、主机防火墙及上游设备允许公网访问 TCP 80、443。
  • 服务器能够通过 HTTPS 访问 ACME 服务,系统时间准确。
  • 已确定证书由哪一层提供:源站 Nginx、负载均衡,还是 CDN 边缘节点。

HTTP-01 验证要求证书机构从公网访问:

http://域名/.well-known/acme-challenge/验证文件

使用 HTTP-01 自动续期时,80 端口不仅要在首次签发时开放,后续验证也要可达。普通请求可以跳转到 HTTPS,但验证目录应直接返回文件,避免被登录验证、访问控制或业务跳转拦截。

香港服务器的地理位置不会改变 ACME 的验证机制。需要检查的是公网可达性、DNS 指向和访问策略,而不是证书是否必须由香港本地机构签发。

如果需要通配符证书,或无法开放 80 端口,应改用 DNS-01。要实现无人值守续期,通常需要 DNS 服务商 API、相应 Certbot 插件及权限受限的凭据;手动添加 TXT 记录不等于已经配置自动续期。

2. 检查运行环境并备份

以下命令适用于 Ubuntu,先进入 root 管理终端:

sudo -i

cat /etc/os-release
command -v nginx || true
command -v certbot || true
systemctl status nginx --no-pager
timedatectl status
ss -lntp | grep -E ':(80|443)\b' || true

若已有 Certbot,再检查来源和版本:

certbot --version
dpkg -l certbot
snap list certbot 2>/dev/null || true

本文统一使用 APT 版本。已有其他安装方式时,应先核对其服务、配置路径和定时任务,不要再混装一套 Certbot。80、443 若被其他服务占用,也不要直接停止进程,应先确认业务归属。

配置改动前备份:

BACKUP="/root/a5https-backup-$(date +%Y%m%d-%H%M%S)"
install -d -m 700 "$BACKUP"

if [ -d /etc/nginx ]; then
    cp -a /etc/nginx "$BACKUP/"
fi

if [ -d /etc/letsencrypt ]; then
    cp -a /etc/letsencrypt "$BACKUP/"
fi

printf '备份目录:%s\n' "$BACKUP"

备份包含证书私钥,应保存在仅管理员可访问的位置,不要放入网站目录、代码仓库或工单附件。

后续命令在同一个 root 终端中执行。设置真实域名和可接收通知的邮箱:

DOMAIN="example.com"
EMAIL="ops@example.com"

example.com 仅为示例,签发前必须替换。

二、逐步签发证书并上线 HTTPS

1. 安装依赖,核验 DNS

如果服务器尚未安装相应软件:

apt update
apt install -y nginx certbot curl openssl ca-certificates dnsutils

nginx -v
certbot --version
openssl version

安装 Nginx 可能启动服务并监听 80 端口。已有生产环境应在变更窗口执行,不要顺带进行无关的软件升级。

检查 DNS:

dig +short A "$DOMAIN"
dig +short AAAA "$DOMAIN"
dig CAA "$DOMAIN"

预期结果:

  • A 记录指向目标服务器,或指向能够正确转发验证请求的入口。
  • AAAA 若存在,不能指向另一台未配置验证目录的服务器。
  • 如果设置了 CAA,应允许 Let’s Encrypt 签发;还要留意父域继承的限制。

域名经过 CDN 时,上述地址通常是边缘节点地址。此时需要保证验证路径能够到达源站,且不被缓存旧响应或附加访问限制。

2. 创建 HTTP 验证站点

下面配置适用于新建的单域名站点。已有业务站点应只合并验证目录配置,保留原有静态文件、反向代理和访问控制逻辑,不要覆盖整个虚拟主机。

先确认目标配置文件不存在:

SITE_CONF="/etc/nginx/sites-available/le-${DOMAIN}"

test ! -e "$SITE_CONF" && echo "可创建新配置"
test ! -e "/etc/nginx/sites-enabled/le-${DOMAIN}" && echo "可创建启用链接"

任一目标已存在时,应停止并检查,不继续执行下面的覆盖写入命令。

创建目录和演示页面:

install -d -m 755 /var/www/acme/.well-known/acme-challenge
install -d -m 755 "/var/www/le-${DOMAIN}"

printf 'HTTPS deployment check\n' > "/var/www/le-${DOMAIN}/index.html"
printf 'acme-probe-ok\n' > /var/www/acme/.well-known/acme-challenge/probe.txt

写入 HTTP 配置:

cat > "$SITE_CONF" <<EOF
server {
    listen 80;
    listen [::]:80;
    server_name ${DOMAIN};

    root /var/www/le-${DOMAIN};
    index index.html;

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/acme;
        default_type text/plain;
        try_files \$uri =404;
    }

    location / {
        try_files \$uri \$uri/ =404;
    }
}
EOF

ln -s "$SITE_CONF" "/etc/nginx/sites-enabled/le-${DOMAIN}"

nginx -t && systemctl reload nginx

若系统禁用了 IPv6,且 nginx -t 因 IPv6 监听失败,应移除对应的 listen [::] 行后重试。不要忽略配置检测错误直接重启服务。

检查本机虚拟主机匹配:

curl --resolve "${DOMAIN}:80:127.0.0.1" \
    "http://${DOMAIN}/.well-known/acme-challenge/probe.txt"

再从服务器之外的终端检查:

curl -i "http://example.com/.well-known/acme-challenge/probe.txt"

成功时应返回 HTTP 200,正文为:

acme-probe-ok

本机成功、外部失败,说明问题更可能在 DNS、安全组、防火墙、CDN 或上游网络,而不是文件本身。仅在服务器上访问自己的域名,不能完整代替公网验证。

3. 使用 webroot 模式签发

执行:

certbot certonly \
    --webroot \
    --webroot-path /var/www/acme \
    --cert-name "$DOMAIN" \
    -d "$DOMAIN" \
    --email "$EMAIL" \
    --agree-tos \
    --non-interactive

这里的 certonly 只申请证书,不让 Certbot 自动修改 Nginx 配置;webroot 模式也不需要停止 Nginx。

成功后检查:

certbot certificates

openssl x509 \
    -in "/etc/letsencrypt/live/${DOMAIN}/cert.pem" \
    -noout -subject -issuer -dates -ext subjectAltName

应能看到正确域名、签发者和有效期。具体有效期以实际证书为准,不在监控脚本里固定假定某个天数。

文件用途如下:

路径用途Nginx 配置方式
live/域名/fullchain.pem站点证书及中间证书链用于 ssl_certificate
live/域名/privkey.pem证书私钥用于 ssl_certificate_key
live/域名/cert.pem站点叶子证书用于检查信息
renewal/域名.conf续期参数由 Certbot 管理,不随意手改

Nginx 应引用 live 下的稳定路径,不要写死 archive 中带编号的文件,也不要把证书复制到另一个目录后忘记同步续期结果。

4. 切换 HTTPS,保留 HTTP 验证入口

先保存当前可用的 HTTP 配置:

cp -a "$SITE_CONF" "$BACKUP/le-${DOMAIN}.http.conf"

下面命令会覆盖本教程刚创建的配置文件,影响该域名的访问方式;已有业务不能直接照抄覆盖。

cat > "$SITE_CONF" <<EOF
server {
    listen 80;
    listen [::]:80;
    server_name ${DOMAIN};

    location ^~ /.well-known/acme-challenge/ {
        root /var/www/acme;
        default_type text/plain;
        try_files \$uri =404;
    }

    location / {
        return 301 https://${DOMAIN}\$request_uri;
    }
}

server {
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name ${DOMAIN};

    ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;

    root /var/www/le-${DOMAIN};
    index index.html;

    location / {
        try_files \$uri \$uri/ =404;
    }
}
EOF

nginx -t && systemctl reload nginx

先检测再平滑重载,可避免因新配置语法错误而主动停止现有服务。此阶段不急于启用长期 HSTS,以免回滚到 HTTP 时客户端仍强制访问 HTTPS。

验证:

curl -I "http://${DOMAIN}/"
curl -I "https://${DOMAIN}/"
curl -i "http://${DOMAIN}/.well-known/acme-challenge/probe.txt"

预期分别为:普通 HTTP 请求跳转到 HTTPS、HTTPS 页面返回 200、验证目录继续直接返回 200。

三、配置自动续期与部署钩子

1. 检查 systemd 定时器

Ubuntu 的 APT 安装方式通常提供 certbot.timer。先查看实际配置:

systemctl cat certbot.timer
systemctl cat certbot.service
systemctl list-timers --all | grep certbot

确认服务调用的是预期 Certbot,再启用:

systemctl enable --now certbot.timer
systemctl status certbot.timer --no-pager
systemctl list-timers --all | grep certbot

应能看到定时器处于等待状态,并有下一次执行时间。若系统不存在该单元,应检查安装来源,不要直接复制其他发行版的定时器配置。

定时器按周期检查证书,但不会每次都重新签发。是否进入续期窗口由 Certbot、证书信息及可用的 ACME 续期机制决定。因此,日志显示“暂不需要续期”通常是正常结果。

不要再同时添加重复的 cron 任务,避免多套调度并行、锁冲突和日志混乱。

2. 添加“续期成功后重载 Nginx”的钩子

证书文件更新,不代表 Nginx 已经载入新证书。应使用部署钩子,而不是无论续期是否发生都重启服务。

确认脚本路径未被占用后创建:

install -d -m 755 /etc/letsencrypt/renewal-hooks/deploy

HOOK="/etc/letsencrypt/renewal-hooks/deploy/20-reload-nginx"

test ! -e "$HOOK" && echo "可创建部署钩子"

如果文件已存在,先检查内容,不覆盖既有运维逻辑。新建脚本:

cat > "$HOOK" <<'EOF'
#!/bin/sh
set -eu

/usr/sbin/nginx -t
/usr/bin/systemctl reload nginx
EOF

chmod 750 "$HOOK"

权限调整仅针对这个脚本,让管理员可执行;不要递归放宽 /etc/letsencrypt 的权限。私钥不应向普通用户开放。

手动验证钩子:

"$HOOK"
systemctl is-active nginx

预期配置检查通过,Nginx 仍为 active。若配置检测失败,脚本会停止,不执行重载;此时应修复 Nginx 配置,而不是删除检测步骤。

该目录中的钩子可能在其他证书成功续期时也执行。若服务器承载多个服务,应评估是否需要按 RENEWED_LINEAGE 区分证书归属,避免无关服务重复重载。

3. 执行续期演练

先运行:

certbot renew --cert-name "$DOMAIN" --dry-run

--dry-run 用于测试验证和续期流程,不替换正式服务证书。合理的成功结果会包含模拟续期通过的信息,但具体文案随版本变化。

默认的模拟续期不应被视为已经验证部署钩子。检查当前版本是否支持显式执行:

certbot --help all | grep -- '--run-deploy-hooks'

若支持,再运行:

certbot renew \
    --cert-name "$DOMAIN" \
    --dry-run \
    --run-deploy-hooks

此操作会在模拟续期成功后执行部署钩子,Nginx 会平滑重载;测试中使用的临时证书不会因此成为线上服务证书。若版本不支持该选项,则分别完成 dry-run 和前面的手动钩子测试,并在首次正式续期后再次核验远端证书。

三、配置自动续期与部署钩子 / 3. 执行续期演练配图

不要用反复执行 --force-renewal 来证明自动续期,避免触发签发限制。

四、从公网检查结果,并按层次处理异常

1. 区分四种验证结果

自动续期验收应覆盖以下四层:

验证层检查对象成功意味着什么
调度层systemd 定时器续期检查会自动触发
签发层dry-run、Certbot 日志验证路径和续期参数可用
部署层钩子、Nginx 配置检测及重载更新后能够载入证书
服务层外部 TLS 连接访问者获得正确证书及证书链

前面三层成功,仍不能省略服务层检查。例如,域名可能指向另一台服务器,或者公网证书实际由 CDN 提供。

2. 检查证书链、域名及线上证书

从外部终端执行,将域名替换为实际值:

openssl s_client \
    -connect example.com:443 \
    -servername example.com \
    -verify_hostname example.com \
    -verify_return_error \
    </dev/null

在系统信任库正常的条件下,应看到证书验证通过,例如 Verify return code: 0 (ok),且没有主机名不匹配错误。

检查服务器本地证书:

openssl x509 \
    -in "/etc/letsencrypt/live/${DOMAIN}/cert.pem" \
    -noout -serial -dates -fingerprint -sha256

提取公网提供的证书:

openssl s_client \
    -connect "${DOMAIN}:443" \
    -servername "$DOMAIN" \
    </dev/null 2>/dev/null |
openssl x509 -noout -serial -dates -fingerprint -sha256

如果 TLS 直接终止在这台 Nginx,本地与公网证书的序列号、指纹应对应。若使用 CDN 或负载均衡,两者可能不同,应分别检查边缘证书和源站证书,不能据此直接判定续期失败。

外部终端直接连接香港源站 Nginx,以及外部终端连接提供公网证书的 CDN 或负载均衡入口;证书标记贴在实际提供证书的节点旁,并展示独立检查源站的路径

要绕开 DNS 路径检查源站,可从外部终端执行:

curl --resolve example.com:443:203.0.113.10 \
    -I https://example.com/

其中 203.0.113.10 是示例地址,必须替换为源站公网 IP。该方式保留域名和 SNI,比直接访问 https://IP地址/ 更适合检查域名证书。

3. 查看日志并设置到期告警

检查续期服务及日志:

journalctl -u certbot.service --since "7 days ago" --no-pager
tail -n 100 /var/log/letsencrypt/letsencrypt.log

手动执行的 Certbot 命令不一定出现在该 systemd 服务日志中,因此两处都应查看。

可以检查本地证书是否会在 14 天内到期:

openssl x509 \
    -in "/etc/letsencrypt/live/${DOMAIN}/cert.pem" \
    -noout -checkend 1209600

echo $?

这里 1209600 为 14 × 24 × 60 × 60 秒。返回 0 表示证书不会在该窗口内到期;非零时需要查看错误信息,区分即将到期、文件缺失或读取失败。

告警窗口应结合证书实际寿命和团队响应时间设置。建议同时监控公网证书到期时间及续期任务失败,不能只监控本地文件。

4. 常见失败按由外到内排查

现象优先检查处理方向
验证连接超时DNS、80 端口、安全组、上游访问策略确认公网能访问验证路径
验证返回 404虚拟主机匹配、webroot、CDN 回源确认请求进入正确目录
IPv4 可用但验证失败AAAA 记录及 IPv6 站点修复 IPv6,或在确认无需 IPv6 后调整 DNS
返回 403、登录页或业务页面认证、重写、WAF、验证路径缓存仅对挑战路径作必要放行
CAA 拒绝签发当前域名及父域 CAA经授权修改签发策略
dry-run 成功,线上仍是旧证书钩子、Nginx 路径、实际 TLS 终止层检查重载及边缘证书配置
nginx -t 失败配置语法、文件存在性、证书与私钥修复后重新检测,勿强行重启
提示锁被占用正在运行的 Certbot、重复调度等待任务结束,清理重复调度
签发次数受限多次正式失败或强制续期先修复验证,再使用测试流程排查

不要为了排障清空防火墙、将私钥改成全员可读,或直接删除 Certbot 锁文件。若必须调整访问策略,应保存原规则,只增加必要范围,并确认 SSH 管理入口不受影响。

五、国密证书如何与这套流程适配

Let’s Encrypt 自动续期和国密证书适配是两项不同的工作。Certbot 不能通过增加一个参数,将普通证书申请变成 SM2 国密证书申请;部署在香港服务器上,也不会改变这一边界。

对象获取与更新方式服务端要求验证重点
Let’s Encrypt 普通 HTTPS 证书Certbot 与 ACME 续期支持相应证书类型的 Nginx/TLS 环境域名、证书链、到期时间、线上证书
SM2 国密证书支持国密的 CA 及其申请、更新流程明确支持目标算法和协议的服务端算法、用途、信任链、客户端兼容
TLCP 等国密服务按具体 CA 和产品方案实施相应国密网关或服务器实现协议协商,以及方案要求的签名、加密证书配套关系

Ubuntu 常规仓库中的 Nginx/OpenSSL 组合不能被默认视为已经满足目标国密服务要求。配置了 TLS 1.3,也不等于启用了国密算法。

实际部署前,需要向 CA 和服务端产品方确认:

  • 提供的是何种证书、协议及算法组合。
  • 是否需要分别配置签名证书和加密证书。
  • 客户端是否支持该协议并信任相应证书链。
  • 是否提供自动更新 API、专用客户端或人工更新流程。
  • 普通浏览器访问和国密客户端访问是否需要独立入口。

业务同时面向普通浏览器和国密客户端时,可以将普通 HTTPS 与国密入口分开部署,再分别验证。不要把 SM2 证书直接填入普通 Nginx 的证书路径后,就认定适配完成;普通 RSA/ECDSA 多证书配置也不等同于国密双证书配置。

如果国密 CA 提供自动化接口,应建立独立的更新流程:申请或下载证书、校验证书用途及密钥配对、检查链完整性、暂存新文件、检测服务配置、受控切换并重载、使用目标国密客户端验证。更新失败时应保留仍有效的旧证书和配置。

普通 HTTPS 可继续由 Certbot 管理,但国密证书不应手动塞入 Certbot 的 live 目录。是否满足特定合规要求,还取决于密码产品、协议实现、证书用途和应用系统要求,不能仅凭一张证书判定。

六、上线验收与回滚检查项

上线验收

  • 域名 A、AAAA 与实际服务入口一致,验证路径从公网返回 200。
  • HTTPS 页面可访问,域名匹配,证书链验证通过。
  • HTTP 普通请求跳转到 HTTPS,挑战路径不被业务规则拦截。
  • Nginx 引用 live 下的证书路径,未引用固定编号或遗漏同步的副本。
  • certbot.timer 已启用,下一次执行时间可查,没有重复调度。
  • dry-run 成功,部署钩子检测和重载成功。
  • 已设置证书到期及续期失败告警,明确告警接收人。
  • CDN、负载均衡、源站和国密入口按各自证书分别验收。
  • 私钥及备份权限受控,备份路径和恢复入口已记录。

配置失败时回滚

对于本文新建站点,如果 HTTPS 配置失败,可恢复之前保存的 HTTP 配置:

cp -a "$BACKUP/le-${DOMAIN}.http.conf" "$SITE_CONF"
nginx -t && systemctl reload nginx

这会撤回该站点的 HTTPS 配置,使其回到 HTTP 演示状态。生产业务若禁止明文访问,应恢复原有的、证书仍有效的 HTTPS 配置,而不是采用此 HTTP 回滚方式。

只恢复本次修改的站点文件,不要直接用整份备份覆盖当前 /etc/nginx,以免撤销同期其他业务变更。若已启用 HSTS,还需考虑客户端缓存对 HTTP 回滚的影响。

若需要撤回新建的部署钩子,可以先将其移出执行目录,保留文件供检查:

mv /etc/letsencrypt/renewal-hooks/deploy/20-reload-nginx \
   "$BACKUP/20-reload-nginx.disabled"

这只适用于本文新建且已确认不被其他业务依赖的脚本。移动后 Certbot 仍可能续期,但不会由该钩子自动重载 Nginx,应及时补上经过验证的替代部署流程。

只有确认系统中其他证书不依赖该定时器时,才考虑停止调度:

systemctl disable --now certbot.timer
systemctl status certbot.service --no-pager

停止定时器不会自动终止已经启动的续期服务,也不会撤销已签发证书。不要手动删除 live、archive 中的文件或修改其链接。确需移除证书时,应先解除所有服务引用、验证配置,再使用 Certbot 的证书管理命令处理。

回滚完成后再次检查 Nginx 状态、业务访问、实际提供的证书及到期时间。旧备份只能恢复文件状态,不能延长证书有效期;恢复服务之后,仍需安排新的续期验证窗口。