Appearance
SSL 证书配置及自动续期指南 (泛域名版)
1. 核心选择:为什么推荐 "泛域名证书"?
你提到的 "不想每次加服务都重新配置 SSL" 和 "免费自动续期",最佳解决方案是申请 泛域名证书 (Wildcard Certificate)。
方案对比
| 特性 | 方案 A: 泛域名 (推荐) | 方案 B: 单域名 (旧方案) |
|---|---|---|
| 证书域名 | *.hongjy.cn (含 blog, home, nas...) | 仅 photo.hongjy.cn (指定一个) |
| 新增子域名 | 无需任何操作,直接复用证书 | 必须重新运行申请命令 |
| 验证方式 | DNS 验证 (需要 API Key) | HTTP 验证 (需要 Nginx 配置) |
| 适用场景 | 想要一劳永逸,子域名很多 | 无法获取 DNS 权限,单体应用 |
| 对旧服务影响 | 无影响。新旧证书可共存 | 无影响 |
关键说明: 你之前印象中 "没有 Key、需要配置 Nginx 验证步骤" 的是 方案 B (HTTP 验证)。 但 方案 B 不支持泛域名。如果你想要 "一次配置,永久通用",必须 使用 方案 A (DNS 验证),这就必须用到阿里云的 API Key 来自动添加 DNS 记录以证明域名归属权。
2. 准备工作 (仅方案 A 需要)
为了申请泛域名证书,我们需要一个只能修改 DNS 的阿里云子账号 (RAM 用户),确保安全。
- 登录 阿里云 RAM 访问控制。
- 创建用户: 用户名如
acme-dns-bot,勾选 "OpenAPI 调用访问"。 - 保存密钥: 复制下来的
AccessKey ID和AccessKey Secret(只显示一次)。 - 授权: 点击用户 -> 权限管理 -> 新增授权 -> 搜索
AliyunDNSFullAccess(管理云解析DNS的权限) -> 确认。
3. 证书申请 (acme.sh Docker 版)
我们使用 Docker 运行 acme.sh,干净且易于管理。
3.1 初始化容器
bash
# 宿主机执行 (首次初始化)
docker run --rm -it \
-v /srv/core/acme:/acme.sh \
neilpang/acme.sh --install-online -m hongjy1991@gmail.com3.2 申请泛域名证书 (DNS API 方式)
请根据你的域名解析服务商选择对应的命令。
选项 A: 腾讯云 (DNSPod) [用户当前使用]
- 获取密钥: 登录 DNSPod 控制台 -> 密钥管理,创建密钥 (API Token)。
- 执行申请:
6.4 ZeroSSL 账户注册报错
- 现象:
acme.sh默认 CA 变更为 ZeroSSL,提示Please update your account with an email address first. - 原因: ZeroSSL 需要关联邮箱账户,或者
acme.sh容器内的账户信息未正确持久化。 - 解决:
- 注册账户 (推荐): 执行一次注册命令 (替换你的邮箱)。bash
docker run --rm -it \ -v /srv/core/acme:/acme.sh \ neilpang/acme.sh --register-account -m hongjy1991@gmail.com - 或者切换回 Let's Encrypt: 在申请命令中显式指定 CA。bash
# 在原命令末尾添加 --server letsencrypt neilpang/acme.sh --issue ... --server letsencrypt
- 注册账户 (推荐): 执行一次注册命令 (替换你的邮箱)。
6.5 No such file or directory 安装失败
现象:
Installing key to: /ssl/hongjy.cn/key.pem后报错cat: ... key: No such file.原因: 上一步申请证书失败 (如上述 ZeroSSL 错误),导致证书文件根本没有生成,自然无法安装。
解决: 先解决申请报错,确保看到
Cert success后,再运行 install 命令。 bash申请 hongjy.cn 和 *.hongjy.cn
docker run --rm -it
-v /srv/core/acme:/acme.sh
-e DP_Id="你的ID"
-e DP_Key="你的Token"
neilpang/acme.sh --issue --dns dns_dp -d hongjy.cn -d *.hongjy.cndocker run --rm -it
-v /srv/core/acme:/acme.sh
-e DP_Id="614622"
-e DP_Key="a215c4a8235ebf83f340bb7c32d69987"
neilpang/acme.sh --issue --dns dns_dp -d hongjy.cn -d *.hongjy.cn
选项 B: 阿里云 (Aliyun)
- 获取密钥: 使用 RAM 子账号获取 AccessKey ID 和 Secret。
- 执行申请:bash
# 申请 hongjy.cn 和 *.hongjy.cn docker run --rm -it \ -v /srv/core/acme:/acme.sh \ -e Ali_Key="你的AccessKey_ID" \ -e Ali_Secret="你的AccessKey_Secret" \ neilpang/acme.sh --issue --dns dns_ali -d hongjy.cn -d *.hongjy.cn
成功提示: 看到
Cert success且输出证书路径,即表示申请成功。证书已保存在宿主机/srv/core/acme/hongjy.cn/下。
4. Nginx 配置与部署
4.1 安装证书到 Nginx
不要直接使用 acme 目录下的证书,使用 install-cert 命令将其复制到 Nginx 专用目录。
bash
# 1. 创建 Nginx SSL 目录
mkdir -p /srv/core/nginx-proxy/ssl/hongjy.cn
# 2. 安装证书 (将证书复制过去,并指定重载命令)
docker run --rm -it \
-v /srv/core/acme:/acme.sh \
-v /srv/core/nginx-proxy/ssl:/ssl \
neilpang/acme.sh --install-cert -d hongjy.cn \
--key-file /ssl/hongjy.cn/key.pem \
--fullchain-file /ssl/hongjy.cn/cert.pem4.2 配置 Nginx (通用模板)
现在,你可以在任何 Nginx 配置文件中使用这个泛域名证书。
示例: nginx-proxy/conf/home.conf
nginx
# HTTP 自动跳转 HTTPS
server {
listen 80;
server_name home.hongjy.cn;
return 301 https://$host$request_uri;
}
# HTTPS 服务
server {
listen 443 ssl http2;
server_name home.hongjy.cn; # 这里的域名可以是任意 *.hongjy.cn
root /srv/site/home;
index index.html;
# ✅ 核心: 引用泛域名证书
ssl_certificate /etc/nginx/ssl/hongjy.cn/cert.pem;
ssl_certificate_key /etc/nginx/ssl/hongjy.cn/key.pem;
# SSL 推荐配置
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
try_files $uri $uri/ /index.html;
}
}未来扩展: 当你要添加
blog2.hongjy.cn时,只需复制上面的server块,修改server_name和root路径即可,无需再申请证书。
5. 自动化续期 (Crontab)
Let's Encrypt 证书有效期 90 天。我们设置每月自动检测续期。
5.1 编写续期脚本
创建 /srv/core/scripts/renew_ssl.sh:
bash
#!/bin/bash
# 日志
LOG_FILE="/var/log/ssl-renew.log"
echo "[$(date)] Starting SSL renewal..." >> $LOG_FILE
# 1. 触发 acme.sh 续期 (DNS 方式无需 Nginx 配合验证)
# 只要证书快过期了 (默认 <60天),它就会自动调用阿里云 API 续期
docker run --rm -v /srv/core/acme:/acme.sh neilpang/acme.sh --cron >> $LOG_FILE 2>&1
# 2. 强制刷新 Nginx 证书文件
# 注意: acme.sh 内部其实记住了 install-cert 的目标,但为了保险我们显式再刷一次
docker run --rm -v /srv/core/acme:/acme.sh -v /srv/core/nginx-proxy/ssl:/ssl \
neilpang/acme.sh --install-cert -d hongjy.cn \
--key-file /ssl/hongjy.cn/key.pem \
--fullchain-file /ssl/hongjy.cn/cert.pem >> $LOG_FILE 2>&1
# 3. 重载 Nginx
docker exec gateway nginx -s reload
echo "[$(date)] Nginx reloaded." >> $LOG_FILE赋予执行权限:
bash
chmod +x /srv/core/scripts/renew_ssl.sh5.2 添加定时任务
bash
crontab -e
# 每月 1 号凌晨 3 点执行
0 3 1 * * /bin/bash /srv/core/scripts/renew_ssl.sh6. (备选) 传统 HTTP 验证方案
仅当你无法获取阿里云 Key 时使用此方案。注意:此方案不支持泛域名,每加一个子域名都要重复操作。
如果你坚持使用旧的 "验证文件" 方式:
- 配置 Nginx: 在
home.conf中添加验证路由:nginxserver { listen 80; server_name home.hongjy.cn; # 验证文件路由 location ^~ /.well-known/acme-challenge/ { alias /usr/share/nginx/html/.well-known/acme-challenge/; } } - 重载 Nginx:
docker exec gateway nginx -s reload - 申请证书 (Webroot 模式):bash
# 必须指定 --webroot,且不支持 *.hongjy.cn docker run --rm -it \ -v /srv/core/acme:/acme.sh \ -v /srv/core/nginx-proxy/html:/usr/share/nginx/html \ neilpang/acme.sh --issue -d home.hongjy.cn --webroot /usr/share/nginx/html - 缺点: 每次新增
xxx.hongjy.cn,都需要先改 Nginx 加location,再跑一遍命令申请。极不推荐。
