使用 acme.sh 自动申请、续期免费的 SSL 证书

HYF Lv4

引言

在现代 Web 开发中,为网站启用 HTTPS 已经不是可选项,而是必选项。无论是保护用户数据安全、提升 SEO 排名,还是避免浏览器弹出“不安全网站”的警告提示,SSL 证书都成为了网站的标配。

虽然很多商业机构提供收费的 SSL 证书,但 Let’s Encrypt 的出现彻底改变了这一格局。作为一个由社区推动的公益项目,Let’s Encrypt 提供免费、自动化、可信任的 SSL 证书,深受开发者喜爱。

不过,手动申请和续期 Let’s Encrypt 证书可能会令人感到繁琐,尤其是在证书每 90 天就需要更新一次的情况下。此时,acme.sh 就显得尤为重要。它是一个基于 Shell 脚本实现的轻量级 ACME 客户端,不仅支持 Let’s Encrypt,还支持 ZeroSSLBuypass 等多家免费 CA,兼容性极强,部署也非常灵活。

在本文中,我将带你一步步了解如何使用 acme.sh 自动申请并续期免费的 SSL 证书,本文主要讲解阿里云 DNS 验证方式,让 HTTPS 的启用和维护变得轻而易举。

acme.sh 简介与安装(Docker 安装方式)

什么是 acme.sh?

acme.sh 是一个用 Shell 编写的轻量级 ACME 客户端,支持通过 ACME 协议从多个证书颁发机构(CA)申请免费的 SSL 证书。默认使用 Let’s Encrypt,也支持 ZeroSSL、Buypass 等其他 CA。相较于官方客户端 certbot,acme.sh 更加轻量、灵活,且支持众多 DNS API,适合脚本化和自动化场景。

为什么选择 Docker 方式部署?

虽然 acme.sh 支持直接通过 Shell 脚本一键安装,但使用 Docker 部署具有以下优点:

与主机系统解耦,不污染环境

更容易跨平台部署

可通过 Docker Compose 管理生命周期

更适合在持续集成、自动化环境中运行

简单的 Docker Compose 配置示例

我们可以使用官方的 Docker 镜像 neilpang/acme.sh 来运行 acme.sh:(非最终完整版,最终完整版请见下文)

1
2
3
4
5
6
7
services:
acme-sh:
image: neilpang/acme.sh
container_name: acme
restart: always
command: daemon
network_mode: host

配置准备

在申请证书之前,我们需要先配置好阿里云 DNS 接口凭证,并指定证书存储路径。以下操作均围绕 docker-compose.yml 文件和 Nginx 环境展开。

获取、配置阿里云 DNS 密钥

首先,登录阿里云控制台后,访问 AccessKey 访问控制台 ,创建一个新的 AccessKey。其他云厂商的 DNS API 配置方法请参考 acme.sh 的官方文档:acme.sh DNS-Api

创建 AccessKey 示例图如下:
创建 AccessKey

接下来,配置阿里云 DNS 所需的密钥。在 acme.sh 所属的 docker-compose.yml 文件中添加以下环境变量,用于在 DNS 验证过程中自动添加解析记录(以阿里云为例):

1
2
3
environment:
- Ali_Key=YOUR_ALIYUN_ACCESS_KEY_ID # 替换为你的阿里云 AccessKeyId
- Ali_Secret=YOUR_ALIYUN_ACCESS_KEY_SECRET # 替换为你的阿里云 AccessKeySecret

配置证书挂载路径

首先需要在 amce.sh 所属的 docker-compose.yml 中添加挂载点:

1
2
3
4
5
6
7
...

volumes:
- /mnt/docker/acme/data:/acme.sh
- /mnt/docker/nginx/ssl/:/installCert/

...

如果你使用 DockerNginx:

确保将容器内的 /mnt/docker/nginx/ssl/ 目录挂载到宿主机,且 Nginx 正确引用该证书( 即:acme.sh 生成的证书文件目录,需与 Nginx 所挂载证书目录一致 ),例如:

Nginx: docker-compose.yml

1
2
3
4
5
6
...

volumes:
- /mnt/docker/nginx/ssl/:/etc/nginx/ssl/

...

Nginx: conf.d/xxx.conf

1
2
3
4
5
6
7
8
9
10
11
12
13
...

server {
listen 443 ssl;
server_name youfeng.ink;

ssl_certificate /etc/nginx/ssl/youfeng.pem;
ssl_certificate_key /etc/nginx/ssl/youfeng.key;

...
}

...

如果你使用 系统安装的 Nginx:

将上文中 amce.sh 所属的 docker-compose.yml 证书输出路径 /mnt/docker/nginx/ssl 改为例如 /etc/nginx/ssl/Nginx 本地真实路径即可

最终完整版docker-compose.yml示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
acme-sh:
image: neilpang/acme.sh
container_name: acme
restart: always
command: daemon
environment:
- Ali_Key=YOUR_ALIYUN_ACCESS_KEY_ID
- Ali_Secret=YOUR_ALIYUN_ACCESS_KEY_SECRET
- TZ=Asia/Shanghai
volumes:
- /mnt/docker/acme/data:/acme.sh
- /mnt/docker/nginx/ssl:/installCert
network_mode: host

直接通过 docker compose up -d 命令启动

快速执行流程

下面是完整的 letsencrypt 证书的申请、安装、自动续期流程,使用 docker exec 在容器中执行 acme.sh 命令

设置默认证书颁发机构

注:默认 SSL server 是 zerossl,我用的是 LetsEncrypt,因为… zerossl 没有魔法环境更新证书时总是会经常 Timeout,导致失败;Let’s Encrypt 的证书有效期为3个月,每3个月得重新申请证书

1
docker exec acme acme.sh --set-default-ca --server letsencrypt

注册 Let’s Encrypt 账户(需要先进行注册才可以正常申请证书)

1
sudo docker exec acme acme.sh --register-account -m your@email.com

申请泛域名证书

1
sudo docker exec acme acme.sh --issue --dns dns_ali -d youfeng.ink -d *.youfeng.ink

泛域名证书需使用 DNS 验证,dns_ali 即表示使用阿里云解析,需将命令中【youfeng.ink】及【.youfeng.ink】替换为自己真实的代码*

安装证书到指定目录

1
2
3
sudo docker exec acme acme.sh --install-cert -d youfeng.ink \
--key-file "/installCert/youfeng.key" \
--fullchain-file "/installCert/youfeng.pem"

需要确保: /installCert/ 已正确挂载到宿主机对应的证书路径中(例如 /mnt/docker/nginx/ssl/)即上文所述:acme.sh 生成的证书文件目录,需与 Nginx 所挂载证书目录一致

设置自动续期任务

添加每日自动续期检查(写入 crontab)实现自动续期,并定期 reload Nginx

1
2
3
4
5
6
7
8
# 清除旧任务
sudo sed -i '/acme.sh --cron/d' /etc/crontab

# 添加新任务:每天 0 点检查并重载 Nginx
# 因为我用的是 docker 部署的 Nginx,所以 Nginx reload 命令为 docker exec nginx nginx -s reload
# 需按照自身部署方式替换此处代码,例如你的 Nginx 不是容器运行的,请改用以下系统命令:
# sudo systemctl restart nginx
echo "0 0 * * * root docker exec acme acme.sh --cron && docker exec nginx nginx -s reload" | sudo tee -a /etc/crontab > /dev/null

执行完命令之后可以通过查看 /etc/crontab 验证是否成功添加定时任务,例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# For details see man 4 crontabs

# Example of job definition:
# .---------------- minute (0 - 59)
# | .------------- hour (0 - 23)
# | | .---------- day of month (1 - 31)
# | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
# | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
# | | | | |
# * * * * * user-name command to be executed

0 0 * * * root docker exec acme acme.sh --cron && docker exec nginx nginx -s reload
~
~
~
~
~
[/etc/crontab][crontab] [Line:16/16,Column:1][100%]
"/etc/crontab" 16L, 535C

自动续期说明

acme.sh 默认会每天执行续期检查任务(通过 –cron),结合上文的 crontab 配置,可实现证书自动续期与 Nginx 自动 reload,无需人工干预

总结

使用 acme.sh 搭配 Docker,是一种高效、灵活且自动化的免费 SSL 证书解决方案。通过 DNS 验证方式,我们不仅能申请到泛域名证书,还能避免端口占用等问题,尤其适合在多服务、多域名环境中部署。

本文中我们完成了:

acme.sh 的 Docker 化部署;
配置阿里云 DNS API,实现自动 DNS 验证;
一键申请和安装泛域名证书;
配置 Nginx 使用证书;
设置自动续期和重载任务,真正实现了“申请一次,放心一整年”。

HTTPSWeb 安全的基础,而 acme.sh 则让它变得触手可及。现在就行动起来,让你的网站告别“不安全”的小红锁吧!

  • 标题: 使用 acme.sh 自动申请、续期免费的 SSL 证书
  • 作者: HYF
  • 创建于 : 2025-06-15 21:35:19
  • 更新于 : 2025-06-16 00:35:32
  • 链接: https://youfeng.ink/acme-1d5b22f2d4e7/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。