阿里云域名 + Nginx + acme.sh 自动申请通配符 HTTPS 证书教程(脱敏版)
本文使用通用示例,不包含真实域名、邮箱、IP、AccessKey 或服务器标识。
请按实际情况替换:
example.comyour-email@example.comYOUR_ACCESS_KEY_IDYOUR_ACCESS_KEY_SECRETYOUR_SERVER_PUBLIC_IP
1. 适用场景
- 服务器运行在阿里云
- 域名 DNS 由阿里云云解析管理
- 服务器已经安装 Nginx
- 需要申请根域名和一级通配符证书
- 需要证书自动续期
- 续期后自动重新加载 Nginx
申请目标:
text
example.com
*.example.com
可覆盖:
text
example.com
www.example.com
admin.example.com
api.example.com
不能覆盖:
text
test.api.example.com
2. 配置域名解析
进入阿里云控制台:
text
云解析 DNS → 权威解析
如果所有一级子域名都指向同一台服务器,可以配置:
| 记录类型 | 主机记录 | 记录值 |
|---|---|---|
| A | @ |
YOUR_SERVER_PUBLIC_IP |
| A | * |
YOUR_SERVER_PUBLIC_IP |
说明:
text
@ 表示根域名 example.com
* 表示所有一级子域名
也可以逐个添加:
text
www A YOUR_SERVER_PUBLIC_IP
admin A YOUR_SERVER_PUBLIC_IP
api A YOUR_SERVER_PUBLIC_IP
3. 放行端口
阿里云安全组建议放行:
text
TCP 80
TCP 443
本教程使用 DNS-01 验证,申请证书本身不依赖 80 端口,但网站访问仍需要开放 80 和 443。
4. 创建阿里云 RAM 用户
不建议在服务器中使用阿里云主账号 AccessKey。
进入:
text
阿里云控制台 → RAM 访问控制 → 用户
创建一个证书申请专用 RAM 用户,例如:
text
acme-dns
创建 AccessKey,并妥善保存:
text
AccessKey ID
AccessKey Secret
可以先授予:
text
AliyunDNSFullAccess
生产环境建议进一步收敛为只允许查询、添加和删除 DNS 解析记录的自定义最小权限。
不要把 AccessKey 写入 Git 仓库、聊天记录、截图或公开日志。
5. 安装 acme.sh
建议使用 root 用户执行:
bash
sudo -i
安装:
bash
curl https://get.acme.sh | sh -s email=your-email@example.com
加载环境变量:
bash
source ~/.bashrc
检查版本:
bash
~/.acme.sh/acme.sh --version
设置默认 CA 为 Let's Encrypt:
bash
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt
6. 配置阿里云 DNS API
在当前终端执行:
bash
export Ali_Key="YOUR_ACCESS_KEY_ID"
export Ali_Secret="YOUR_ACCESS_KEY_SECRET"
变量名必须保持:
text
Ali_Key
Ali_Secret
首次成功调用后,acme.sh 会保存相关配置,后续自动续期通常不需要再次手工导出。
7. 申请根域名和通配符证书
执行:
bash
~/.acme.sh/acme.sh --issue \
--server letsencrypt \
--dns dns_ali \
-d example.com \
-d '*.example.com' \
--keylength ec-256
参数说明:
text
--dns dns_ali 使用阿里云 DNS API
-d example.com 申请根域名
-d '*.example.com' 申请一级通配符域名
--keylength ec-256 使用 ECC P-256 私钥
通配符参数建议使用单引号:
bash
-d '*.example.com'
8. 将证书安装到 Nginx 目录
创建目录:
bash
mkdir -p /etc/nginx/ssl/example.com
安装证书:
bash
~/.acme.sh/acme.sh --install-cert -d example.com \
--ecc \
--key-file /etc/nginx/ssl/example.com/private.key \
--fullchain-file /etc/nginx/ssl/example.com/fullchain.pem \
--reloadcmd "nginx -t && nginx -s reload"
因为申请时使用了:
bash
--keylength ec-256
所以安装和续期时必须带:
bash
--ecc
设置权限:
bash
chmod 600 /etc/nginx/ssl/example.com/private.key
chmod 644 /etc/nginx/ssl/example.com/fullchain.pem
9. 配置 Nginx HTTPS
9.1 WebSocket 公共配置
创建:
bash
vi /etc/nginx/conf.d/00-websocket-map.conf
内容:
nginx
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
该 map 只配置一次,不要在多个站点文件中重复定义。
9.2 前端站点示例
nginx
server {
listen 80;
server_name www.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name www.example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
root /path/to/web;
index index.html;
location / {
try_files $uri $uri.html $uri/ /index.html;
}
location ~ ^/(api|v1)(/|$) {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_set_header X-Forwarded-Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
9.3 管理端示例
nginx
server {
listen 80;
server_name admin.example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
server_name admin.example.com;
ssl_certificate /etc/nginx/ssl/example.com/fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/example.com/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
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_set_header X-Forwarded-Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
检查并重新加载:
bash
nginx -t && systemctl reload nginx
10. 查看自动续期任务
acme.sh 安装后通常会自动创建 crontab:
bash
crontab -l
示例:
cron
17 0 * * * "/root/.acme.sh/acme.sh" --cron --home "/root/.acme.sh" > /dev/null
含义:
text
每天检查一次证书是否需要续期
并不是每天都重新签发。
11. 建议启用续期日志
编辑:
bash
crontab -e
将任务改成:
cron
17 0 * * * "/root/.acme.sh/acme.sh" --cron --home "/root/.acme.sh" >> /var/log/acme-renew.log 2>&1
查看日志:
bash
tail -n 100 /var/log/acme-renew.log
实时查看:
bash
tail -f /var/log/acme-renew.log
12. 验证证书
查看 acme.sh 证书列表:
bash
~/.acme.sh/acme.sh --list
查看本地证书:
bash
openssl x509 \
-in /etc/nginx/ssl/example.com/fullchain.pem \
-noout \
-subject \
-issuer \
-dates \
-ext subjectAltName
检查线上证书:
bash
openssl s_client \
-connect www.example.com:443 \
-servername www.example.com \
</dev/null 2>/dev/null |
openssl x509 \
-noout \
-subject \
-issuer \
-dates \
-ext subjectAltName
13. 测试自动续期
测试 cron 检查流程:
bash
/root/.acme.sh/acme.sh --cron --home /root/.acme.sh
强制测试一次续期:
bash
~/.acme.sh/acme.sh --renew \
-d example.com \
--ecc \
--force
成功后应看到类似:
text
Cert success.
Installing key to: /etc/nginx/ssl/example.com/private.key
Installing full chain to: /etc/nginx/ssl/example.com/fullchain.pem
Running reload cmd: nginx -t && nginx -s reload
Reload successful
--force 仅用于首次验证,不要频繁执行。
14. 常见问题
Nginx 报 unknown directive "http2"
旧版本 Nginx 不支持:
nginx
http2 on;
改为:
nginx
listen 443 ssl http2;
如果仍不支持,先使用:
nginx
listen 443 ssl;
检查模块:
bash
nginx -V 2>&1 | grep http_v2_module
页面返回 502
502 Bad Gateway 通常不是证书问题,而是 Nginx 无法连接后端。
检查 Docker 端口:
bash
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
如果容器映射为:
text
0.0.0.0:3000->3000/tcp
Nginx 应配置:
nginx
proxy_pass http://127.0.0.1:3000;
测试:
bash
curl -v http://127.0.0.1:3000/
查看错误日志:
bash
tail -n 100 /var/log/nginx/error.log
路径写错
不要保留教程中的示例路径:
text
/etc/nginx/ssl/example.com/
应替换成自己的真实域名目录。
通配符证书不能覆盖根域名
单独申请:
text
*.example.com
不能覆盖:
text
example.com
因此必须同时申请:
bash
-d example.com
-d '*.example.com'
15. 流程总结
text
创建阿里云 RAM 用户
↓
获取专用 AccessKey
↓
安装 acme.sh
↓
配置 Ali_Key 和 Ali_Secret
↓
使用 dns_ali 申请根域名和通配符证书
↓
安装证书到 Nginx 正式目录
↓
Nginx 配置 HTTPS
↓
acme.sh 每天自动检查续期
↓
续期成功后自动检查并重新加载 Nginx