Nginx + acme.sh SSL 自动化部署指南

Implementing free certificate renewal using acme.sh

Posted by byron han on February 3, 2026

1. 安装 acme.sh

由于网络环境原因,这里使用 Gitee 镜像源进行安装。

1
2
3
4
5
6
7
8
9
10
11
12
# 1. 克隆代码
git clone https://gitee.com/neilpang/acme.sh.git
cd acme.sh/

# 2. 安装 (邮箱用于接收证书过期预警,建议填写)
./acme.sh --install -m h@xx.com

# 3. 安装完成后刷新环境变量,使 acme 命令生效
source ~/.bashrc

# 4. 确认版本
acme.sh --version

2. 生成/签发证书

我们使用 Webroot 模式。这种模式下,Nginx 不需要停机,acme.sh 会在网站根目录下放置验证文件,CA 服务器通过访问该文件来验证域名所有权。

  • 域名xx.com
  • 网站根目录/home/uat/xhs (确保该目录存在且 Nginx 有读取权限)
1
acme.sh --issue -d xx.com --webroot /home/uat/xhs

💡 提示:如果申请的是泛域名(如 *.xx.com),则需要使用 DNS API 模式,无法使用 Webroot 模式。

3. 安装证书到 Nginx

证书签发后,需要将其复制到 Nginx 的配置目录,并设置 Nginx 自动重载。

这是最关键的一步,因为 acme.sh 默认证书存储路径复杂,我们自定义为标准路径:

1
2
3
4
acme.sh --install-cert -d xx.com \
--key-file       /usr/local/nginx/cert/sy.key \
--fullchain-file /usr/local/nginx/cert/sy.pem \
--reloadcmd     "/usr/local/nginx/sbin/nginx -s reload"

参数说明:

  • --key-file: 私钥路径。
  • --fullchain-file: 全链证书路径(包含服务器证书和中间证书,注意部分旧配置用的是 cert-file,但 Nginx 推荐用 fullchain)。
  • --reloadcmd: 非常重要。证书自动续期成功后,acme.sh 会自动执行这个命令让 Nginx 加载新证书。

4. Nginx 配置方案

在 Nginx 配置目录(/usr/local/nginx/conf/conf.d/)下修改对应的 sy.conf

⚠️ 关键修改说明:防止自动续期失败

你的当前配置将所有 80 端口请求都 301 跳转到了 HTTPS。 为了自动续期能正常工作,HTTP 80 端口的配置块中,必须在跳转之前,允许外网访问验证目录 /.well-known/acme-challenge/

以下是基于你原有配置优化后的完整 Nginx 配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# HTTP Server - 强制跳转 HTTPS
server {
    listen 80;
    server_name xx.com;

    # 【关键配置】:必须保留这个 location,否则续期会失败
    # 告诉 Nginx:如果是来验证证书的请求,去 /home/uat/xhs 目录找文件,不要做跳转
    location ^~ /.well-known/acme-challenge/ {
        root /home/uat/xhs; 
        # 不需要默认索引,仅仅允许访问文件
        default_type "text/plain"; 
    }

    # 其他所有请求全部跳转到 HTTPS
    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS Server - 启用 HTTP/2
server {
    # 监听 443 端口,启用 ssl 和 http2 (需确认 Nginx 编译了 http_v2_module)
    listen 443 ssl http2;
    server_name xx.com;

    # SSL 证书配置 (对应 acme.sh 安装的路径)
    ssl_certificate      /usr/local/nginx/cert/sy.pem;
    ssl_certificate_key  /usr/local/nginx/cert/sy.key;

    # SSL 安全配置推荐 (现代浏览器标准)
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # --- 以下是你原有的业务配置 ---
    client_header_timeout 3m;
    client_body_timeout 3m;
    send_timeout 3m;
    client_max_body_size 500m;

    proxy_connect_timeout 1000s;
    proxy_read_timeout 1000s;
    proxy_send_timeout 1000s;

    access_log  /usr/local/nginx/logs/sy_access.log;
    error_log   /usr/local/nginx/logs/sy_error.log;

    proxy_redirect  off;
    proxy_set_header  Cookie $http_cookie;
    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;
    proxy_max_temp_file_size 0;
    
    proxy_buffer_size          4k;
    proxy_buffers              4 32k;
    proxy_busy_buffers_size    64k;
    proxy_temp_file_write_size 1024k;

    # 前端静态文件服务
    location / {
        root /home/uat/xhs;
        index  index.html index.htm;
        try_files $uri $uri/ /index.html;
    }
}

修改后务必测试配置:

1
2
3
/usr/local/nginx/sbin/nginx -t
# 如果成功,则重载
/usr/local/nginx/sbin/nginx -s reload

5. 维护与排查

查看证书状态

1
acme.sh --info -d xx.com

查看自动续期任务

acme.sh 安装后会自动创建 crontab 任务,你不需要手动写 cron。

1
crontab -l | grep acme.sh

测试自动续期 (模拟)

不要等到证书过期才测试。使用 --force 强制续期一次:

1
acme.sh --renew -d xx.com --force

观察最后是否输出了 Reload success,如果有,说明自动化链路是完全通畅的。

备注说明

  • ECC 证书:如果你在申请时指定了 --keylength ec-256,上述所有命令都需要加上 --ecc 参数。目前你的环境是 ECC 模式。
  • 证书升级:默认使用的是 ZeroSSL,如果想换回 Let’s Encrypt,可以执行 acme.sh --set-default-ca --server letsencrypt