SSL证书自动续签

申请 HTTPS 证书(比如 Let’s Encrypt)之前,CA 必须确认一件事:

认证原理

认证方式

申请 HTTPS 证书(比如 Let’s Encrypt)之前,CA 必须确认一件事:

你真的控制这个域名

这个过程叫 域名控制验证(DCV, Domain Control Validation)。 DNS-01、HTTP-01、TLS-ALPN-01 都是 不同的验证手段

HTTP-01 的思路最直观。CA 会给你一段随机字符串,让你把它作为一个文件放到网站目录里,路径固定在 /.well-known/acme-challenge/。随后 CA 通过普通的 HTTP 请求访问你的域名,如果能访问到这个文件并且内容正确,就认为你控制了这个域名。它的前提条件是域名必须能被公网通过 80 端口访问,而且访问路径不能被反向代理、CDN 或跳转破坏。因为验证的是具体主机名,所以它不支持泛域名。

DNS-01 的思路完全不同,它不关心你的服务器和端口,而是只看 DNS。CA 会要求你在域名的 DNS 里添加一条特定的 TXT 记录,记录名一般是 _acme-challenge.域名,值是一串校验字符串。CA 从公网 DNS 查询这条记录,只要查得到,就说明你能控制这个域名的 DNS,因此验证通过。由于泛域名的控制权本身就是通过 DNS 体现的,所以 DNS-01 是唯一支持 *.example.com 泛域名证书的方式。它的代价是需要 DNS 提供商的 API 权限,并且要等待 DNS 解析在公网生效。

TLS-ALPN-01 则介于两者之间。CA 会直接连接你的域名的 443 端口,在 TLS 握手阶段通过 ALPN 扩展请求一个特殊的协议标识。你的 ACME 客户端需要在这一瞬间临时提供一个只用于验证的证书,如果 CA 在 TLS 层验证成功,就认定你控制了该域名。这种方式不需要 80 端口,但要求 443 必须直连你的服务,不能被很多 CDN、七层代理或证书托管平台拦截,因此实际使用范围比较小,同样不支持泛域名。

下面是一张对照表,把三种方式的差异压缩到一起,方便快速判断使用场景:

认证方式CA 验证你什么需要的网络条件是否支持泛域名典型适用场景
HTTP-01能否访问指定 HTTP 文件公网 80 端口直达普通直连网站
DNS-01能否查到指定 DNS TXT只需能改 DNS泛域名、CDN、内网、反代
TLS-ALPN-01TLS 握手阶段响应公网 443 端口直达无法开 80 的直连服务

自动续订

证书自动续订的本质其实只有一句话: ACME 客户端定期尝试重新做一次“同样的域名验证”,成功就续,不成功就失败。 三种方式的差别不在“续不续”,而在于续订时依赖的外部条件是否还成立

HTTP-01 的自动续订逻辑是这样的:acme.sh(或 certbot)通过 cron / systemd 定期运行,当证书快到期时,它再次在服务器上生成 /.well-known/acme-challenge/ 里的校验文件,然后 CA 通过 HTTP 访问你的域名。如果 80 端口还能直连到这台服务器、路径没有被改写、没有被 CDN/代理拦截,那么续订会悄无声息地成功;一旦中途网络结构变了,比如加了 CDN、端口被封、跳转到 HTTPS 或转发到别的地方,续订就会在你没注意时失败。这也是 HTTP-01 最容易“过几个月突然挂”的原因。

DNS-01 的自动续订逻辑最干净。acme.sh 到期前运行时,会再次调用 DNS API,自动添加新的 TXT 记录,等待解析生效,然后让 CA 去查,成功后再把 TXT 删掉。只要三件事没变:域名还在你手里、DNS 还是这个服务商、API Key 没过期,续订就可以长期全自动运行,哪怕服务器本身是内网、关机、换 IP,证书依然能续。泛域名证书的续订也完全一样,不需要额外操作。

TLS-ALPN-01 的自动续订逻辑依赖 443 端口。续订时,ACME 客户端会临时监听 443,准备一个专门用于验证的证书,CA 发起 TLS 连接并检查 ALPN 响应。如果你的 443 端口始终直连、没有被 CDN、ESA、Cloudflare 这类平台接管,续订可以自动完成;但只要中间多了一层代理、证书托管、四层转发不透明,CA 的验证请求就到不了你的 ACME 客户端,续订会直接失败。

脚本使用

先说通用规律:acme.sh 的签发命令核心是 --issue,域名用 -d(可写多个),验证方式用 --dns / --webroot / --alpn(三选一),签发后用 --install-cert 把证书落到你服务需要的位置,并配合 --reloadcmd 重载服务。自动续订一般不需要你每次手动执行,acme.sh 默认会安装定时任务(cron 或 systemd timer),到期前自动跑 --cron 去续。

一、脚本基本使用(通用)

1)签发(一次性)

  • --issue:申请/签发证书
  • -d example.com:要签发的域名;多个域名就写多个 -d

2)安装证书(落地到固定路径,供 Nginx/Caddy/面板读取)

  • --install-cert:把证书复制到你指定的路径(不会改变 acme.sh 自己的存储)
  • --key-file:私钥路径
  • --fullchain-file:完整链(最常用)
  • --cert-file / --ca-file:有些程序要分开(多数用不到)
  • --reloadcmd:安装/续订后执行的命令,比如重载 nginx

3)续订(一般自动)

  • --renew -d example.com:手动续订某个域名
  • --cron:acme.sh 定时任务实际跑的入口(你也可以手动跑验证续订链路是否通)

二、常用参数解释(你会经常见到这些)

参数作用什么时候用
--issue申请/签发证书第一次申请、或强制重签
-d指定域名(可多次)单域、多域、含 www
--force强制重新签发调试/更换验证方式/不想等到期
--debug 2输出更详细日志出错排查
--log / --log /path写日志(默认/指定文件)需要留存排查证据
--server letsencrypt指定 CA(默认就是 LE)换 ZeroSSL/自建 CA 时
--keylength ec-256 / 2048指定密钥类型/长度想用 ECC 或 RSA
--dnssleep 60DNS-01 等待解析生效秒数DNS 传播慢时必备
--install-cert把证书安装到你的路径给 Nginx/面板用
--reloadcmd "..."安装或续订后重载服务nginx/caddy/apache
--set-default-ca设置默认 CA多环境统一
--list列出已签发证书检查现状
--ecc使用 ECC算法生成证书
RSA:2048 位密钥
ECC:256 位密钥(安全级别相当甚至更高)
更快、更省资源、证书更小,而且对现在的浏览器和系统来说几乎没有兼容性问题。
--standalone当你用 --standalone 时,acme.sh 会在本机 临时监听端口不用现有的 Web 服务器,服务器没有web的时候,可以使用独占
-k选择具体证书算法使用-k ec-256 指定使用 ECC P-256 椭圆曲线证书
在 acme.sh 里,它和 --ecc 的效果基本等价。
--set-default-ca当前指定的 CA(server)写入配置作为默认值需要和--server参数一起使用才有作用
--server指定申请证书的 ACME 服务端(CA)letsencrypt

可以使用

acme.sh --info

查看配置信息

image-20251227210623183

三、三种验证方式:脚本怎么写、参数怎么选

1)DNS-01(你现在的 --dns dns_ali

核心点:用 DNS API 自动加 TXT 记录完成验证。以阿里云为例要先准备环境变量(只要做一次):

bash
export Ali_Key="你的AccessKeyId"
export Ali_Secret="你的AccessKeySecret"

签发示例:

bash
~/.acme.sh/acme.sh --issue -d example.com --dns dns_ali --dnssleep 60

泛域名示例:

bash
~/.acme.sh/acme.sh --issue -d example.com -d "*.example.com" --dns dns_ali --dnssleep 60

DNS-01 续订为什么稳:到期前自动再走一遍“加 TXT → 验证 → 删 TXT”。你要确保的只有:域名 DNS 仍在阿里云、Ali_Key/Ali_Secret 没失效。

你这条命令里的 --dns dns_ali 具体含义就是:选择 acme.sh 内置的 “Aliyun DNS 插件”,用阿里云 DNS API 做 TXT 校验。

2)HTTP-01(webroot 模式最常见)

核心点:CA 通过 80 访问你站点某个目录下的挑战文件。你需要告诉 acme.sh:挑战文件应该写到哪个目录(也就是网站的 webroot)。

签发示例(假设网站根目录是 /var/www/html):

bash
~/.acme.sh/acme.sh --issue -d example.com --webroot /var/www/html

多域名示例:

bash
~/.acme.sh/acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html

HTTP-01 自动续订的关键条件:80 必须能访问到这台机器且路径不被改写;很多“过几个月突然续不上”就是因为后来上了 CDN/反代/强制跳转,把 /.well-known/acme-challenge/ 搞坏了。

3)TLS-ALPN-01(alpn)

核心点:CA 直接连 443,通过 TLS 握手的 ALPN 扩展验证。要求 443 必须直连到运行 acme.sh 的地方,且不能被很多 CDN/证书托管平台接管。

签发示例:

bash
~/.acme.sh/acme.sh --issue -d example.com --alpn

TLS-ALPN-01 自动续订的关键条件:443 必须始终直连、且 acme.sh 在续订时能接管/响应对应握手验证;一旦前面有 ESA、Cloudflare 这类托管证书的东西,通常会失败。

TLS-ALPN-01(--alpn)需要临时占用 443 端口;如果 443 已经被 Nginx 监听,通常必须先停掉 Nginx(或让 Nginx 把 443 完整让出来)

四、落地安装与续订后的自动重载(强烈建议你加上)

以 Nginx 为例(DNS-01/HTTP-01/TLS-ALPN-01 都一样用这段安装):

bash
~/.acme.sh/acme.sh --install-cert -d example.com \
  --key-file       /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/example.com.fullchain.pem \
  --reloadcmd     "systemctl reload nginx"

这样证书续订成功后会自动更新到你指定的位置并 reload nginx,你不用手动管。

具体执行脚本

1、把 acme.sh 的安装脚本下载下来并立刻执行,安装一个 ACME 客户端(acme.sh)

bash
curl https://get.acme.sh | sh

get.acme.sh 在 GitHub / raw.githubusercontent.com 上)

加速:

把官方安装脚本的下载地址换成镜像:
curl -fsSL https://ghproxy.com/https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh
或:
curl -fsSL https://ghproxy.net/https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh

2、安装 socat 这个网络“端口转发/套接字工具”。

bash
apt install socat

因为刚开始安装acme.sh安装会警告:

bash
[2025年12月27日 20:40:45] It is recommended to install socat first.
[2025年12月27日 20:40:45] We use socat for the standalone server, which is used for standalone mode.
[2025年12月27日 20:40:45] If you don't want to use standalone mode, you may ignore this warning.

3、添加软连接

bash
ln -s  /root/.acme.sh/acme.sh /usr/local/bin/acme.sh

4、执行证书

如果直接执行:

bash
acme.sh --install-cert -d maluyao.top

会告诉你

[2025年12月27日 20:46:29] The domain 'maluyao.top' is not a cert name. You must use the cert name to specify the cert to install.
[2025年12月27日 20:46:29] Cannot find path: '/c/Users/maluyao/.acme.sh/maluyao.top'

因为这是安装证书命令不是申请证书

可以使用acme.sh --list查看本机已经拥有的证书

--register-account这台机器“认领一个 CA 身份”

--issue给某个域名“发证”

--install-cert把证书放到程序真正用的地方

接下来执行途中:

acme.sh --issue -d maluyao.top

要求选择模式:

image-20251227205236177

直接使用还是需要前置条件:

image-20251227212007440

也就是先执行注册账户:

acme.sh --register-account -m my@example.com

然后就直接注册好了

--nginx实际上会执行nginx命令,所以需要先安装nginx

sudo apt update
sudo apt install -y nginx

事实上--nginx 的前提是:nginx 已经有一个站点配置里写了 server_name jocker.me; 否则 acme.sh 不知道该改哪个 vhost 来放挑战文件,所以报这句。然后换成--standalone模式了

不管咋样成功之后:image-20251227212851848

使用crontab -l可以看到自动续订程序:image-20251227213518498

系统每天早上 6 点 40 分,都会悄悄运行一次 acme.sh,让它看看你现在的证书有没有快过期。如果没快过期,它什么都不干;如果快到期了,就自动去续期。整个过程是后台执行的,你平时完全感觉不到。

--cron 代表“我现在是定时任务模式”,不是给你手动签新证书用的,而是专门负责续期的。 --home "/root/.acme.sh" 是告诉它:证书、配置、账号都在这个目录里。 最后的 > /dev/null 就是把所有输出丢掉,不在终端显示,也不给你发邮件,所以你看起来它一直很“安静”。image-20251227213850416

强制更新会安装到指定目录:image-20251227214050786

其他

证书标准:

--key-file(私钥):

常见后缀在哪些软件/场景里常见
.keynginx / apache / haproxy(最常见)
.pem通用 PEM 格式(OpenSSL / acme.sh 默认)
.privkeyacme.sh / certbot 有时用
.ecdsa.keyECC 私钥(人为命名,便于区分)

--fullchain-file(完整证书链)

常见后缀在哪些软件/场景里常见
.crtnginx / apache(非常常见)
.pemOpenSSL / 通用
.cerWindows / Java 生态
.fullchain.pemacme.sh / certbot 习惯命名

Tomcat(Java)最常用的是 keystore.p12/.pfx.jks。所以后缀怎么选,本质取决于你走哪条路。

对 Tomcat 来说无所谓,.pem.key.crt 都只是名字。关键是文件内容分别是私钥和证书。

推荐:

私钥:叫 privkey.pem(或 privkey.key 也行) 完整链:叫 fullchain.pem(或 fullchain.crt 也行)

不过,Tomcat 最省事、最标准的做法是把它们合成一个 PKCS12 文件给 Tomcat 用:

bash
openssl pkcs12 -export \
  -inkey /path/privkey.key \
  -in /path/fullchain.pem \
  -name tomcat \
  -out /path/tomcat.p12

openssl pkcs12 -export -inkey privkey.key  -in fullchain.pem  -name springboot -out server.p12
->让后让你输入密码
可以添加参数取消密码:
-passout pass:ChangeMe123

#这里 .p12 后缀就是标准选择(.pfx 也可以,本质一样)。
# -name 的真实含义是给导入到 PKCS#12(.p12/.pfx)里的“私钥 + 证书”起一个“别名(alias)”
# keystore(JKS / PKCS12)是 可以同时装多套证书的
# 👉 一个 server.p12 里可以同时包含多组「私钥 + 证书链」
# 👉 每一组通常对应 一个域名 / 一张证书
# 👉 用 alias(别名) 来区分
#然后在 Tomcat server.xml 里通常这么配(不同版本写法略有差异,但核心是 keystore):
keystoreFile=".../tomcat.p12"
keystoreType="PKCS12"
keystorePass="你导出时设置的密码"
server:
  port: 443
  ssl:
    enabled: true
    key-store: classpath:server.p12
    key-store-type: PKCS12
    key-store-password: ChangeMe123
    key-alias: springboot

查看工具:

查看 p12 里包含什么(证书链/私钥/alias 等)

openssl pkcs12 -info -in server.p12

不显示私钥(更安全)

openssl pkcs12 -info -in server.p12 -nokeys
openssl pkcs12 -info -in server.p12 -noout
keytool -list -v -keystore server.p12 -storetype PKCS12

三方托管

Snipaste_2025-12-27_02-47-21

阿里云的DNS验证

1.登录阿里云后右上角头像点击AccessKey

image-20251227181943401

2.点击使用RAM用户 AccessKey

image-20251227182014864

3.直接点击执行配置即可,会自动创建出Key和Secret

image-20251227182302564

Linux定时任务

Linux 里其实不止一种“定时任务系统”,而是好几套并存的,各自解决不同场景的问题。下面我按人类理解的方式,一口气给你讲清楚它们是干嘛的、用什么命令加/删/看。

最传统、最常见的是 cron(crontab)。 它适合“每天几点几分”“每周一次”“固定周期”的任务,比如你看到的 acme.sh 自动续期。

cron 的特点是: 只要机器开着,到点就执行;机器如果关机错过了时间,它不会补跑。

你常用的命令是: crontab -l —— 查看当前用户的定时任务 crontab -e —— 编辑(增加 / 修改 / 删除)当前用户的定时任务 crontab -r —— 直接删除当前用户的全部定时任务(很危险,一般不用)

cron 是“按用户分的”,root 和普通用户互不影响。

acme.sh 默认就会自动装一条 crontab

bash
root@instance-20251220-091822:~# crontab -l
0 0 * * * root bash ~/.acme.sh/acme.sh --cron -f >/dev/null 2>&1

执行命令:

bash
# 1. 看证书文件本身在服务器上是不是新的
~/.acme.sh/acme.sh --list

# 2. 强制续一次
~/.acme.sh/acme.sh --renew -d google.cogrise.top --force

# 3. 手动重启服务,强制吃新证书
systemctl restart xray

评论

评论加载中……