Skip to content

手动更新 SSL 证书:按环境替换并检查结果 ​

选择网站使用的部署环境,将新证书替换到现有网站中,再检查更新结果。

选择部署环境 ​

本教程仅用于操作引导与示例演示。读者应自行评估生产环境的网络架构、HTTPS 入口、软件版本、部署方式及业务要求,对文中的命令和配置进行适配,并在测试环境验证后再应用于生产环境。

示例使用 example.com,请将域名、文件名、路径、服务名和端口替换为实际值。完成对应环境的更新步骤后,请按文末的更新后检查确认结果。

新证书使用了新的私钥时,两者需要一起替换;继续使用原私钥时,应确认它与新证书匹配。下方文件替换命令中的私钥源路径,应填写已准备好的匹配私钥副本,避免将源路径和目标路径设为同一文件。

Nginx:替换证书文件并重载 ​

  1. 找到目标网站的 server 配置块,记下 ssl_certificate 和 ssl_certificate_key 指向的文件路径。准备替换的证书链文件应包含新的网站证书及配套中间证书,网站证书在前,中间证书在后。
  2. 备份原证书链和私钥,将新证书链和匹配私钥上传到仅允许必要管理员访问的暂存目录。
  3. 修改下方变量并执行命令,完成文件替换、配置检查和服务重载,保留原网站配置。

若这些文件由自动任务维护,请先与维护人员确认本次手动更新方式;需要暂停任务时,确认正在运行的任务已结束后再备份和替换。

以下命令适用于 Nginx 主进程以 root 身份运行、目标路径指向普通文件且目标目录已存在的 Linux 环境。请按实际路径修改变量后执行,命令会覆盖指定的目标文件:

bash
NEW_CHAIN='/path/to/new/fullchain.pem'
NEW_KEY='/path/to/new/privkey.pem'
TARGET_CHAIN='/etc/nginx/tls/example.com/fullchain.pem'
TARGET_KEY='/etc/nginx/tls/example.com/privkey.pem'
sudo install -m 644 -o root -g root "$NEW_CHAIN" "$TARGET_CHAIN" &&
sudo install -m 600 -o root -g root "$NEW_KEY" "$TARGET_KEY" &&
sudo nginx -t && sudo systemctl reload nginx

文件替换发生在配置检查和服务重载之前。如果配置检查失败,请先修复问题;此时磁盘上的文件可能已被替换,但运行中的 Nginx 仍可能使用原证书。必要时恢复备份文件,重新检查配置;检查通过后重载服务,再检查网站访问和实际使用的证书。

使用容器、非 root 主进程、符号链接或其他部署工具时,应通过原有发布方式更新文件和权限。

Apache:更新 VirtualHost 引用的文件 ​

  1. 找到目标网站的 HTTPS <VirtualHost> 配置块,记下 SSLCertificateFile 和 SSLCertificateKeyFile 指向的文件路径。
  2. 备份原证书、私钥和网站配置,将新证书链和匹配私钥上传到暂存目录。
  3. 修改下方变量并执行命令,将新文件复制到第一步记录的路径。示例适用于 Apache 2.4.8 及以上、主进程以 root 身份运行,且目标路径为普通文件的环境。

若这些文件由自动任务维护,请先确认本次手动更新不会被任务覆盖;需要暂停任务时,确认任务已结束后再备份和替换。

bash
NEW_CHAIN='/path/to/new/fullchain.pem'
NEW_KEY='/path/to/new/privkey.pem'
TARGET_CHAIN='/etc/apache2/tls/example.com/fullchain.pem'
TARGET_KEY='/etc/apache2/tls/example.com/privkey.pem'
sudo install -m 644 -o root -g root "$NEW_CHAIN" "$TARGET_CHAIN" &&
sudo install -m 600 -o root -g root "$NEW_KEY" "$TARGET_KEY"

目标目录应已存在,Rocky Linux 请填写实际 /etc/httpd/ 下的路径。其他运行方式应沿用原文件部署方式和服务账号权限。如果原配置单独引用中间证书链文件,请分别更新网站证书和中间链文件,不要直接套用合并链的示例。

  1. 文件替换成功后,检查配置并重载服务。根据系统选择下面一组命令,Debian/Ubuntu 使用:
bash
sudo apache2ctl configtest && sudo systemctl reload apache2

在 Rocky Linux 等使用 httpd 的环境中,执行以下命令检查配置并重载服务:

bash
sudo httpd -t && sudo systemctl reload httpd

请按实际配置替换服务名。如果配置检查失败,磁盘上的文件已经改变,请修复问题或恢复仍可用的备份文件,检查通过后再重载服务。

Tomcat:更新密钥库并加载 ​

  1. 在 server.xml 中找到提供 HTTPS 的 Connector,记下密钥库路径、格式、证书别名(Alias)和密码配置。
  2. 查看新 JKS 或 PKCS12 密钥库的格式、密码和证书别名,确认其中包含新证书、匹配私钥和中间证书链。使用 keytool 查看时,Tomcat 使用的条目类型应为 PrivateKeyEntry,检查方法见证书格式指南。
  3. 在安排好的维护时间,备份原密钥库和 Connector 配置。如果新文件的密码或别名发生变化,先修改 Connector 中的对应值,再执行下方命令完成文件替换、读取权限检查和重启。

不要直接沿用旧密码。 KeyManager 导出的密码记录在同次导出的 readme 中;导出时留空会随机生成密码,新文件的密码可能与原配置不同。

若密钥库由自动部署任务维护,请先确认本次手动更新方式,必要时暂停任务并等待当前执行结束。以下示例适用于 systemd 管理的 tomcat10 服务、普通 JKS 文件路径且目标目录已存在的环境:

bash
NEW_KEYSTORE='/path/to/new/server.jks'
TARGET_KEYSTORE='/etc/tomcat10/tls/example.com.jks'
sudo install -m 640 -o root -g tomcat "$NEW_KEYSTORE" "$TARGET_KEYSTORE" &&
sudo -u tomcat test -r "$TARGET_KEYSTORE" &&
sudo systemctl restart tomcat10

请按实际环境替换服务名、用户和组。等待应用启动后,检查日志和网站访问。即使 Tomcat 进程已运行,也要确认 HTTPS Connector 正常工作,且业务可以正常访问。启动失败时,请检查密码、证书别名、中间证书链和文件权限,必要时恢复仍可用的原密钥库与配置。

IIS:导入新 PFX 并更新已有绑定 ​

若原绑定由自动任务维护,请在操作前确认手动修改不会被覆盖,必要时暂停任务并等待当前执行结束。

  1. 进入 IIS 管理器,选择目标网站,打开“绑定”。记下需更新条目的 IP、端口、主机名、SNI 设置和当前证书。
  2. 在服务器节点打开“服务器证书 → 导入”,选择包含匹配私钥的新 PFX,输入该文件的密码。KeyManager 导出的密码可在同次导出的 readme 中查看。沿用原绑定使用的证书存储,例如“个人”或“Web Hosting”。
  3. 回到原网站的 HTTPS 绑定,点击“编辑”,将“SSL 证书”改为刚导入的新证书,保留原 IP、端口、主机名和 SNI 设置。
  4. 保存后,使用浏览器或客户端重新连接网站,按更新后检查确认结果。更新普通 IIS 证书绑定通常无需重启整个 IIS。

在检查完成前保留原证书。需要恢复时,在同一绑定中重新选择仍有效、未被吊销且带有匹配私钥的原证书。

HAProxy:替换合并后的 PEM 文件并重载 ​

  1. 找到 HTTPS bind 中 crt 指定的证书文件路径,或检查其引用的 crt-list。确认目标 PEM 文件中的证书覆盖当前网站的域名。
  2. 备份原 PEM 文件和配置,将新证书链和匹配私钥上传到暂存目录。
  3. 修改下方变量并执行脚本,完成证书链与私钥合并、目标文件替换、配置检查和服务重载。

若该文件由自动任务维护,请在操作前确认本次手动更新方式,必要时暂停任务并等待当前执行结束,再备份和替换。

以下命令适用于 HAProxy 主进程以 root 身份运行、由 systemd 管理,且证书路径指向普通 PEM 文件的环境。目标目录需已存在:

bash
sudo bash -c 'set -eu
NEW_CHAIN="/path/to/new/fullchain.pem"
NEW_KEY="/path/to/new/privkey.pem"
TARGET="/etc/haproxy/certs/example.com.pem"
CONFIG="/etc/haproxy/haproxy.cfg"
umask 077
TMP=$(mktemp "${TARGET}.tmp.XXXXXX")
trap '\''rm -f -- "$TMP"'\'' EXIT
cat "$NEW_CHAIN" > "$TMP"
printf "\n" >> "$TMP"
cat "$NEW_KEY" >> "$TMP"
chown root:root "$TMP"
chmod 600 "$TMP"
mv -- "$TMP" "$TARGET"
haproxy -c -f "$CONFIG" && systemctl reload haproxy'

配置检查在文件替换后进行,失败时不会执行重载,但目标文件已经改变。需要恢复时,复制回仍可用的原 PEM,再检查并重载。

宝塔:在目标网站替换证书内容 ​

以下以宝塔 Linux 面板管理的 Nginx 网站为例:

若已启用面板或外部工具的自动续期,请在操作前确认本次手动更新不会被覆盖,必要时暂停任务并等待当前执行结束。

  1. 打开“网站 → 目标网站 → 设置 → SSL → 当前证书”,核对域名,备份当前证书和私钥。
  2. 将新证书的完整证书链复制到“证书(PEM 格式)”,将匹配私钥的完整内容复制到“密钥(KEY)”。保留文件的开头、结尾标记和全部内容。
  3. 保存证书,确认面板提示成功。保留现有 HTTPS 端口、强制跳转、HSTS 及其他业务设置。
  4. 通过网站的实际访问地址,确认返回的是新证书,且业务访问正常。

如果面板提示加载失败,请检查证书与私钥是否匹配,以及 Nginx 配置是否有误。需要恢复时,将仍可用的原证书链和私钥填回同一网站,保存后重新检查网站访问。界面入口随版本有所不同,可参考宝塔部署图示。

1Panel:导入新证书并让网站使用该证书 ​

以下以 1Panel v2 管理的 OpenResty 网站为例,先导入新证书,再让指定网站使用该证书:

如果网站由自动更新任务维护,请在操作前与维护人员确认更新方式。新证书记录有独立的 ID;使用固定证书 ID 的任务需要同步调整目标记录,不能在网站切换后继续更新旧记录。

  1. 在“网站 → 证书”中找到原证书,记下原证书记录和关联网站,确认本次需要更新哪些网站。
  2. 通过“上传证书”导入新证书链与匹配私钥,核对新记录的域名、有效期和 ID。文件导入步骤见 1Panel 部署指南。
  3. 进入目标网站的“配置 → HTTPS”,在“已有证书”中选择刚导入的新记录,保留网站原有 HTTPS 设置并保存。
  4. 让本次需要更新的其他关联网站也选择新证书,并逐个检查网站访问和证书。在确认相关网站均已使用新证书前,请保留原证书记录。

需要恢复绑定时,重新选择仍有效、未被吊销的原证书记录,并再次检查网站访问。

Kubernetes:更新已有 TLS Secret ​

  1. 确认当前集群、命名空间(Namespace)和网站入口,记录 Ingress 的 spec.tls[].secretName,或 Gateway HTTPS 监听中的 tls.certificateRefs。
  2. 确认该 Secret 所在的命名空间、由谁维护,以及哪些入口引用它。由 cert-manager、Helm 或 GitOps 管理时,应通过原管理流程更新,避免手动修改被控制器或后续发布覆盖。
  3. 备份现有 Secret 和入口配置,将备份保存在仅允许必要管理员访问的位置,并准备新证书链和匹配私钥。
  4. 更新原 Secret 的 tls.crt 和 tls.key,保留入口引用。下面示例适用于手动维护、已存在且类型为 kubernetes.io/tls 的 Secret;需要 kubectl 和 Python 3。

在 Bash 中执行,先替换变量。脚本只修改两个数据项,不打印证书或私钥内容:

bash
set -o pipefail
NAMESPACE='web'
TLS_SECRET='web-tls'
NEW_CHAIN='/path/to/new/fullchain.pem'
NEW_KEY='/path/to/new/privkey.pem'

kubectl create secret tls "$TLS_SECRET" -n "$NAMESPACE" \
  --cert="$NEW_CHAIN" --key="$NEW_KEY" --dry-run=client -o json |
  python3 -c 'import json,sys; print(json.dumps({"data": json.load(sys.stdin)["data"]}))' |
  kubectl patch secret "$TLS_SECRET" -n "$NAMESPACE" \
    --type=merge --patch-file=/dev/stdin

命令使用管道传递私钥,执行时应关闭 Shell 命令跟踪,避免将中间 JSON 数据写入公开日志。Secret 更新后,检查入口控制器是否已加载新证书,再通过网站的实际域名访问并检查证书。加载方式取决于所用的入口控制器,无需因此默认重启应用 Pod。

入口继续引用同一个 Secret,无需为换证重新创建 Ingress 或 Gateway。手动维护的 Secret 需要恢复时,使用仍可用的备份证书链和匹配私钥执行相同的数据更新,再逐一检查引用它的入口。由其他工具管理时,应通过原管理流程恢复,避免恢复结果被覆盖。

应用直接挂载 Secret 时如何加载?

如果证书由应用直接读取,而非 Ingress 或 Gateway 使用,需要按应用的部署方式重新读取文件或重启。使用 subPath 挂载时,还需处理挂载内容的更新。这与本节入口控制器加载证书的流程不同。

更新后检查 ​

  1. 重新访问网站:在自己的电脑上打开网站的完整 HTTPS 地址,确认访问的是目标域名和端口,且浏览器没有证书错误提示。
  2. 查看证书:点击地址栏左侧的网站信息按钮,打开连接信息和证书查看器。确认证书覆盖当前访问的域名,且仍在有效期内。不同浏览器的入口名称可能略有不同。
  3. 确认已换成新证书:比较网站实际证书与本地新证书的 SHA-256 指纹,确认一致。下方提供 OpenSSL 命令,也适用于新旧证书到期日相同的情况。
  4. 检查业务功能:确认图片和页面样式显示正常,登录、接口等业务功能可用。网站由程序访问时,还应使用该程序确认连接和证书校验正常;使用 HTTPS 回源时,也需检查回源连接。
  5. 检查本次更新范围:本次证书用于多个节点、端口或 IPv4/IPv6 入口时,逐一确认这些位置已更新。CDN、WAF 等前置平台可能使用独立证书,浏览器看到的也可能是平台证书;请分别确认平台和源站的证书是否需要更新。

使用 OpenSSL 精确比较指纹 ​

以下命令适用于已安装 OpenSSL 的终端。请替换文件路径、域名和端口,先查看本地新的网站证书:

sh
openssl x509 -in /path/to/new/server.pem -noout -serial -dates -fingerprint -sha256

再查看网站实际返回的证书:

sh
openssl s_client -connect example.com:443 -servername example.com </dev/null \
  | openssl x509 -noout -serial -dates -fingerprint -sha256

以上命令用于查看证书信息,比较两次输出中的 sha256 Fingerprint 即可确认指纹是否一致。

完成检查后,记录本次更新结果并设置下次到期提醒。操作前暂停了自动更新任务时,请先与维护人员确认任务将使用正确的证书、文件路径或记录,再按计划恢复。如需自动完成后续签发和部署,可参考自动化与续期中的对应教程。

参考资料 ​