大陆服务器用 acme.sh 自动续期证书,最大的障碍是 GitHub 访问受限,以及腾讯云 DNS 插件的配置。下面这份教程针对你 Debian 系统 + 腾讯云 DNS 的环境,用 Gitee 镜像绕过 GitHub,实现一次配置、自动续期。
📦 第一步:安装依赖与 acme.sh(走 Gitee 镜像)
Debian 最小化系统可能缺 git、cron、socat,先补齐。由于 get.acme.sh 会访问 GitHub 导致卡死,直接用 Gitee 镜像克隆安装。
# 1. 安装依赖
apt update
apt install -y git cron socat curl
# 2. 从 Gitee 镜像克隆(不要用 curl get.acme.sh)
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh
# 3. 安装(替换为你的邮箱,用于接收续期失败提醒)
./acme.sh --install -m 你的邮箱@example.com
# 4. 让命令生效
source ~/.bashrc🔑 第二步:获取腾讯云 DNS API 密钥
acme.sh 通过腾讯云 API 自动添加 DNS 验证记录,因此需要一个有 DNS 权限的密钥。建议用子账号,权限最小化。
在腾讯云控制台按以下路径操作:
- 创建策略:访问管理 → 策略 → 新建自定义策略 → 按策略语法创建,粘贴以下内容:
{
"statement": [
{
"action": [
"dnspod:DescribeRecordFilterList",
"dnspod:DescribeRecordList",
"dnspod:CreateRecord",
"dnspod:DeleteRecord"
],
"effect": "allow",
"resource": ["*"]
}
],
"version": "2.0"
}- 创建子用户:访问管理 → 用户列表 → 新建用户 → 快速创建 → 访问方式选编程访问 → 关联刚创建的策略。
- 记录生成的 SecretId 和 SecretKey。
⚙️ 第三步:配置密钥并切换 CA
acme.sh 默认用 ZeroSSL,申请通配符证书时容易触发限流。建议切换为 Let's Encrypt,对通配符支持更稳定。
# 导入腾讯云密钥(可写入 ~/.bashrc 持久化)
export Tencent_SecretId="你的SecretId"
export Tencent_SecretKey="你的SecretKey"
# 切换默认 CA
acme.sh --set-default-ca --server letsencrypt📜 第四步:签发证书
使用 dns_tencent 插件,支持同时签发主域名和泛域名。国内服务器检测海外 DNS 容易超时,加上 --dnssleep 强制等待,跳过本地检测。
acme.sh --issue --dns dns_tencent \
-d example.com -d '*.example.com' \
--dnssleep 120把 example.com 换成你的实际域名。执行后等待约 2 分钟,看到 Cert success 即签发成功。acme.sh 会自动创建 cron 定时任务,后续到期前自动续签。
📂 第五步:安装证书到 Nginx 路径
不要直接在 Nginx 里引用 ~/.acme.sh/ 目录下的文件,必须用 --install-cert 复制到指定位置,并设置重载命令,这样续期后 Nginx 才能自动加载新证书。
# 创建证书存放目录
mkdir -p /etc/nginx/ssl
# 安装证书(域名替换为你自己的)
acme.sh --install-cert -d example.com \
--key-file /etc/nginx/ssl/example.com.key \
--fullchain-file /etc/nginx/ssl/example.com.pem \
--reloadcmd "systemctl reload nginx"🌐 第六步:Nginx 配置(含自定义 404)
在 Debian 下,配置文件放在 /etc/nginx/sites-available/ 比较规范。新建站点配置:
nano /etc/nginx/sites-available/example.com.conf写入以下内容(域名和路径按需替换):
# HTTP 跳转 HTTPS
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
# HTTPS 主配置
server {
listen 443 ssl;
server_name example.com www.example.com;
ssl_certificate /etc/nginx/ssl/example.com.pem;
ssl_certificate_key /etc/nginx/ssl/example.com.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
root /var/www/html;
index index.html;
# 自定义 404
error_page 404 /404.html;
location = /404.html {
root /var/www/html;
internal;
}
location / {
try_files $uri $uri/ =404;
}
}创建自定义 404 页面:
nano /var/www/html/404.html写入任意 HTML 内容即可。
启用站点并重载:
ln -s /etc/nginx/sites-available/example.com.conf /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx如果你的站点是反向代理(
proxy_pass到后端),需要在location /里加proxy_intercept_errors on;,否则后端返回的 404 不会触发 Nginx 的自定义页面。
✅ 第七步:验证自动续期
crontab -l | grep acme.sh看到类似 0 0 * * * "/root/.acme.sh"/acme.sh --cron ... 的输出,说明定时任务已生效。acme.sh 每天检查一次,到期前约 30 天自动续签,并通过 --reloadcmd 自动重载 Nginx,你后续不需要手动操作。
⚠️ 几个容易踩的坑
Gitee 镜像版本可能偏旧:如果后续执行 --issue 时报错 dns_tencent 不存在,说明镜像太旧。可以尝试从 Gitee 上找更新时间较近的同步仓库,或者先升级 acme.sh(acme.sh --upgrade,但可能又走 GitHub 导致失败)。更稳妥的做法是克隆后先检查 dnsapi/dns_tencent.sh 文件是否存在。
--dnssleep 120 不是必须的,但建议保留:国内服务器请求海外 DNS 验证接口时,本地检测容易超时。加上这个参数会让 acme.sh 添加 TXT 记录后直接等待,让 Let's Encrypt 官方去验证,避免因本地网络问题误报失败。
密钥安全:Tencent_SecretId 和 Tencent_SecretKey 不要直接写在命令历史里长期留存。写入 ~/.bashrc 时注意文件权限,或者用 export 临时设置后及时清理历史。