使用 acme.sh + Nginx 实现 SSL 证书自动申请与续期

支持腾讯云 DNS 和阿里云 DNS 自动验证

https://songshiyu.cn/archives/wei-ming-ming-wen-zhang-Itp9zREG

一、前言

本教程介绍如何使用 acme.sh 脚本配合 Nginx 实现 SSL 证书的自动申请和续期。通过 DNS 验证方式,无需停止 Web 服务即可完成证书申请。

二、环境准备

系统要求

  • Ubuntu / Debian 系统(其他 Linux 发行版类似)
  • 已安装 Nginx
  • 拥有域名管理权限(腾讯云或阿里云)

1. 安装 Nginx 并设置开机自启

# 更新软件包列表
sudo apt update

# 安装 Nginx
sudo apt install nginx -y

# 启动 Nginx 服务
sudo systemctl start nginx

# 设置开机自启
sudo systemctl enable nginx

# 验证 Nginx 状态
sudo systemctl status nginx

三、安装 acme.sh 自动续签脚本

1. 安装 acme.sh

# 使用官方脚本安装,替换 your@email.com 为你的邮箱

curl https://get.acme.sh | sh -s email=your@email.com

2. 修改默认证书签发机构

# 设置默认使用 Let's Encrypt(推荐)
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

四、配置云服务商 API

腾讯云 API 获取步骤:

> 图片说明:

> 1. 登录腾讯云控制台 → 访问管理 → API 密钥管理

> 2. 点击「新建密钥」

> 3. 复制 SecretId 和 SecretKey

1. 登录 [腾讯云控制台](https://console.cloud.tencent.com/)

2. 进入「访问管理」→「API 密钥管理」

3. 点击「新建密钥」

4. 保存 SecretId 和 SecretKey(注意:SecretKey 只显示一次,请妥善保存)

重要提示:腾讯云 DNSPod 和腾讯云 API 是不同的,本教程使用腾讯云 API(dns_tencent),不是 DNSPod API(dns_dp)。

阿里云 API 获取步骤:

> 图片说明:

> 1. 登录阿里云控制台 → 访问控制 → AccessKey

> 2. 点击「创建 AccessKey」

> 3. 复制 AccessKey ID 和 AccessKey Secret

1. 登录 [阿里云控制台](https://www.aliyun.com/)

2. 进入「访问控制」→「AccessKey 管理」

3. 点击「创建 AccessKey」

4. 保存 AccessKey ID 和 AccessKey Secret

配置 API 密钥到 acme.sh

编辑 acme.sh 账户配置文件:

nano ~/.acme.sh/account.conf
# 腾讯云 API(注意与 DNSPod API 区分)
export SAVED_Tencent_SecretId="你的SecretId"
export SAVED_Tencent_SecretKey="你的SecretKey"

阿里云 API 配置:
export SAVED_Ali_Key="你的AccessKey ID"
export SAVED_Ali_Secret="你的AccessKey Secret"

保存并退出(Ctrl+O,回车,Ctrl+X)。

五、申请 SSL 证书

执行证书申请命令:

# 腾讯云 DNS 验证:
# 申请单个子域名证书
~/.acme.sh/acme.sh --issue --dns dns_tencent -d test.yourdomain.com

# 申请泛域名证书(推荐,可保护所有子域名)
~/.acme.sh/acme.sh --issue --dns dns_tencent -d yourdomain.com -d *.yourdomain.com


# 阿里云 DNS 验证:
# 申请单个子域名证书
~/.acme.sh/acme.sh --issue --dns dns_ali -d test.yourdomain.com

# 申请泛域名证书(推荐,可保护所有子域名)
~/.acme.sh/acme.sh --issue --dns dns_ali -d yourdomain.com -d *.yourdomain.com

申请成功后,证书文件默认保存在:

~/.acme.sh/你的域名_ecc/
├── 你的域名.cer      # 证书文件
├── 你的域名.key      # 私钥文件
├── ca.cer            # CA 中间证书
├── fullchain.cer     # 完整证书链(证书 + CA)
└── 你的域名.conf     # 配置文件

六、配置 Nginx

修改 Nginx 配置:

sudo nano /etc/nginx/nginx.conf
# 补充在http块中,根据自己的域名修改路径
server {
    listen 443 ssl http2;
    server_name test.yourdomain.com;

    # 证书配置(使用 fullchain.cer 和 .key 文件)
    ssl_certificate     /root/.acme.sh/test.yourdomain.com_ecc/fullchain.cer;
    ssl_certificate_key /root/.acme.sh/test.yourdomain.com_ecc/test.yourdomain.com.key;

    # SSL 安全增强配置
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 1d;
    ssl_session_cache   shared:SSL:50m;
    ssl_stapling        on;
    ssl_stapling_verify on;

    # 网站根目录
    root /var/www/yourdomain;
    index index.html;

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

# HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name test.yourdomain.com;
    return 301 https://$host$request_uri;
}
# 测试 Nginx 配置语法
sudo nginx -t

# 重载 Nginx 配置
sudo systemctl reload nginx

七、反向代理配置

如果你有一个运行在本地端口的服务(如 http://127.0.0.1:1180),希望通过域名 HTTPS 访问:

# HTTP 自动跳转 HTTPS
server {
    listen 80;
    server_name pic.yourdomain.com;
    return 301 https://$host$request_uri;
}

# HTTPS 反向代理
server {
    listen 443 ssl http2;
    server_name pic.yourdomain.com;

    # SSL 证书配置
    ssl_certificate     /root/.acme.sh/pic.yourdomain.com_ecc/fullchain.cer;
    ssl_certificate_key /root/.acme.sh/pic.yourdomain.com_ecc/pic.yourdomain.com.key;

    # SSL 安全增强配置
    ssl_protocols       TLSv1.2 TLSv1.3;
    ssl_ciphers         ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers on;
    ssl_session_timeout 1d;
    ssl_session_cache   shared:SSL:50m;

    # 反向代理配置
    location / {
        proxy_pass http://127.0.0.1:1180;
        
        # 转发真实 IP 和协议信息
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        
        # WebSocket 支持(如果需要)
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

优势

  • 只需开放 80/443 端口
  • 内部端口(如 1180)不直接暴露在外网
  • 自动获得 HTTPS 加密和 HTTP/2 支持

八、自动续期验证

acme.sh 安装时会自动添加 cron 定时任务:

crontab -l | grep acme.sh

输出示例:
0 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

这表示每天凌晨自动检查并续期即将过期的证书。

手动测试续签:

# 手动执行续期命令(测试用)
~/.acme.sh/acme.sh --cron --home ~/.acme.sh

操作 命令
安装 acme.sh `curl https://get.acme.sh
设置 CA ~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
腾讯云申请 ~/.acme.sh/acme.sh --issue --dns dns_tencent -d domain.com
阿里云申请 ~/.acme.sh/acme.sh --issue --dns dns_ali -d domain.com
泛域名申请 ~/.acme.sh/acme.sh --issue --dns dns_ali -d domain.com -d *.domain.com
查看证书 ~/.acme.sh/acme.sh --list
续期测试 ~/.acme.sh/acme.sh --cron --home ~/.acme.sh
删除证书 ~/.acme.sh/acme.sh --remove -d domain.com
Nginx 测试 sudo nginx -t
Nginx 重载 sudo systemctl reload nginx