什么是 acme.sh?为什么用 acme.sh?
acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书
——摘自 acme.sh Github 项目介绍
简单来说,acme.sh 可以帮助你无痛申请并部署免费的 ssl 证书
而相较于 Let’s Encrypt 在她官网推荐的 Certbot 客户端,acme.sh 支持更多的DNS厂商,比方说 DNSPod(使用腾讯云注册域名时默认的 DNS 厂商),在使用 DNS 验证方式验证时更省时省力
并且由于 acme.sh 100%使用 shell 编写,因此你也并不需要做什么软件适配即可使用,也基本不会产生软件冲突(目前我使用经验)
并且,不管你是谁,你无需 root 权限即可安装 acme.sh
(如果你使用 Webroot mode 申请证书,由于申请过程中需要将文件写入网站根目录,最好还是使用 root 来安装,当然,这是后话)
而且她有 Docker 部署方式 (什么 Docker Fans )
(相信你一定会爱上她的)
目前 acme.sh 支持以下方式申请证书:
- 网站根目录文件验证 (需要用户拥有网站根目录写权限)
- 独立验证 (需要安装 socat 服务)
- tls alpn 独立验证 (需要安装 socat 服务)
- Apache 服务验证 (可替代网站根目录文件验证)
- Nginx 服务验证 (可替代网站根目录文件验证)
- DNS 验证 (需要申请 DNS API 或手动添加 DNS 解析)
- DNS CNAME 验证(请查阅官方文档)
- 服务配置模式验证(请查阅官方文档)
本文参考 acme.sh 官方文档和笔者个人经验书写
如果你对本文有任何问题,欢迎在下方评论区友好讨论
少说多做开始动手
具体的操作文档你可以点击此处查看
如果你需要有关Docker部署方面的教程,请在左边菜单选择 给 Docker Fans 的一点小参考
章节
⚠️ 注意!本文仅介绍基本的用法,详细用法请前往 acme.sh 查看
安装acme.sh
仅需要一条命令即可安装 acme.sh
但请注意,你需要将my@example.com
这一段替换为你自己的邮箱
curl https://get.acme.sh | sh -s email=my@example.com
你也可以先克隆 GIT 仓库来安装
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
在国内 (较差) 网络环境下,你可以使用此条命令安装
git clone --depth 1 https://gitee.com/neilpang/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
由于自动更新证书需要使用 crond 服务来运行,因此你需要先安装 crond 服务再安装 acme.sh
当然你也可以添加 --nocron
参数来在无 crond 服务下安装,只不过证书自动更新将无法使用
curl https://get.acme.sh | sh -s email=example@example.com --nocron
安装后的tips
在安装过程中,acme.sh 自动写入了你的.bashrc
文件,这让你可以像使用命令一样调用她
也就是说,你不需要在 acme.sh 安装目录下就可以调用她
由于 acme.sh 默认 CA 为 ZeroSSL,而在我本人实际使用中发现 ZeroSSL 似乎不太喜欢国内的网络环境,而 Let’s Encrypt 却完全能够承受
那,我们先换个 CA 再说
acme.sh --set-default-ca --server letsenctypt
letsenctypt 字段可以更换为 acme.sh 默认支持的 CA 或支持 acme 协议的链接
点击查看 acme.sh 默认支持的CA
由于 acme.sh 目前经常更新,因此建议在使用之前将其自动更新打开并检查一遍更新
acme.sh --upgrade --auto-upgrade
申请证书吧!
但是,在申请之前,我还是希望你能够看看这些内容:
- 接下来的内容中,我将用
example.com
作为申请域名,你需要将此域名更换为你自己的域名 - 在申请过程中如果出现任何错误,你可以添加
—-debug
参数来 debug(废话)
本文不会研究如何 debug - 你可以申请多种类型的证书,仅需在申请命令后方添加参数
—-keylength (2048|3072|4096|8192|ec-256|ec-384|ec-521)
- 你可以同时为多个域名申请证书。当你同时为多个域名申请证书时,一般而言,你的申请命令中第一个出现的域名即为证书的主域名。如果你不确定证书的主域名是哪一个,可以使用
acme.sh —-list
来查看 - 当你同时为多个域名申请证书时,如果你仅指定一种验证方式,那么所有的网址都将使用这一种的方式进行验证。当然,你也可以为不同的域名指定不同的验证方式,其类似于这样的格式:
acme.sh --issue
-d aa.com -w /home/wwwroot/aa.com
-d bb.com --dns dns_cf
-d cc.com --apache
-d dd.com -w /home/wwwroot/dd.com
那么现在,我们开干吧
DNS 验证
DNS 验证分为自动 DNS 验证(需要 DNS 厂商提供 API )和手动 DNS 验证,其中手动 DNS 验证方式不支持自动续签
仅 DNS 验证支持申请泛域名证书
(有可能 DNS CNAME 验证也可以?我到时候试试)
自动DNS验证
在此之前,请你先打开这个网页:acme.sh支持的自动DNS验证厂商列表
现在,你需要找到你的域名当前使用的DNS厂商,这里选择常用的Cloudflare
和DNSPod
举例子
(部分厂商有特殊的自动验证的要求,这就是为什么看文档总比看别人写的文章好的原因)
Cloudflare
Cloudflare 有两种API密钥,一种是区域密钥,一种是全局密钥
点击此处前往 API 获取页面
使用全局密钥的话,当然会更加简便,但也会增加安全风险
全局密钥需要你的Cloudflare 全局密钥
和Cloudflare 登录邮箱
,而区域密钥需要你的用户 Token
和区域 ID
要查看你的全局密钥,请在你的 API 页面的Global API Key
这一行点击查看按钮获取你的全局密钥
要使用区域密钥,请点击创建令牌
-> 编辑区域 DNS
-> 区域资源下选择你的域名
-> 创建令牌
来获取你的用户 Token ,你可以在你的网站概述
下找到你的域名区域 ID
使用全局密钥
export CF_Key="Your Cloudflare Global API Key"
export CF_Email="Your Cloudflare Login Email"
使用区域密钥
export CF_Zone_ID="Your Cloudflare Website Zone ID"
export CF_Token="Your Cloudflare User API Token"
最后我们来申请证书吧!
acme.sh --issue --dns dns_cf -d example.com -d *.example.com
DNSPod
甚至DNSPod官方都有 acme.sh on DNSPod 的教程
如果一切正常,那么你的证书将会被自动下载
手动 DNS 验证
acme.sh --issue --dns -d example.com
--yes-I-know-dns-manual-mode-enough-go-ahead-please
你会得到类似这样的回应:
[Sun Feb 11 18:52:50 CST 2024] Add the following TXT record:
[Sun Feb 11 18:52:50 CST 2024] Domain: "_acme-challenge.example.com"
[Sun Feb 11 18:52:50 CST 2024] TXT value: "xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
这时请你添加一条 DNS 解析:
- 解析类型为
TXT
- 名称为上方输出中
Domain
的内容,在本例中为_acme-challenge.example.com
⚠ 注意,一般情况下在添加 TXT 解析时 dns 厂商会自动帮你添加example.com
字段 - 内容为上方输出中
TXT value
的内容,在本例中为xxxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx
当添加完 DNS 解析之后,请你使用此条命令继续申请证书
acme.sh --issue --renew -d example.com
--yes-I-know-dns-manual-mode-enough-go-ahead-please
如果一切正常,那么你的证书将会被自动下载
网站根目录文件验证
作为最朴素(也是最简单)的验证方式,你只需要指定你的域名绑定的网站根目录即可完成验证
本例中以/home/wwwroot/example.com
作为网站根目录
acme.sh --issue -d example.com -w /home/wwwroot/example.com
如果一切正常,那么你的证书将会被自动下载
独立验证
独立验证也有两种方式,但其实都差不多
如果你的服务器并没有运行网站服务,此时用此种验证方式会更为简单
适用于没有任何服务绑定了 80 端口或者 443 端口的服务器类型
由于此种方式依赖于 socat 服务,我们需要先安装 socat 服务
#For RHEL Series
sudo dnf install -y socat
#For Debian Series
sudo apt install -y socat
此种验证方式需要监听 80/443 端口,因此你需要使用 root 权限来进行验证
使用 80 端口
acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
使用 443 端口
acme.sh --issue --alpn -d example.com -d www.example.com -d cp.example.com
如果一切正常,那么你的证书将会被自动下载
网站服务验证
网站服务验证,顾名思义,你需要先安装 nginx 或者 Apache httpd 这二者其中一个服务方可使用。
她会更改你的网站服务配置,但请放心,证书签发完成之后都会给你改回来
其实在实际上,根据我的测试,
网站服务验证
只是服务配置模式验证
的自动化而已
其实也是网站根目录文件验证
的另外一种方式
Nginx 服务验证
acme.sh --issue --nginx -d example.com -d www.example.com -d cp.example.com
Apache 服务验证
acme.sh --issue --apache -d example.com -d www.example.com -d cp.example.com
如果一切正常,那么你的证书将会被自动下载
安装证书吧!
由于 acme.sh 并不会自动帮我们更改网站服务(如 nginx 和 Apache httpd )的配置文件,因此我们需要手动告诉 acme.sh 要将签发下来的证书放置在哪里,并执行什么命令使网站服务重载或重启
在此用以 nginx 为网站服务的服务器为例:
- 我们安装的证书是以
example.com
为主域名的证书 - 将公钥文件写入
/etc/nginx/conf.d/ssl/server.crt
文件 - 将私钥文件写入
/etc/nginx/conf.d/ssl/server.key
文件 - 将CA证书写入
/etc/nginx/conf.d/ssl/ca.crt
文件 - 将FullChain文件写入
/etc/nginx/conf.d/ssl/fullchain.pem
文件 - 命令nginx服务器重新加载配置文件的命令为
nginx -s reload
那么,我们的命令应该是这个样子
acme.sh --install-cert -d example.com
--cert-file /etc/nginx/conf.d/ssl/server.crt
--key-file /etc/nginx/conf.d/ssl/server.key
--ca-file /etc/nginx/conf.d/ssl/ca.crt
--fullchain-file /etc/nginx/conf.d/ssl/fullchain.pem
--reloadcmd "nginx -s reload"
在你执行此命令过后,如果一切正常,你将在你指定的位置发现你的证书(他们很乖的)
如果你同时指定了 —-reloadcmd
,acme.sh会尝试运行指定的重载命令并将命令运行时的输出打印出来
如果在 acme.sh 运行重载命令时报错也不要担心,你只需要调整好你的 —-reloadcmd
并且将上面的安装证书命令在运行一次,此时 —-reloadcmd
将会被覆盖为最新的指定命令
⚠️注意:光申请证书而不修改任何配置文件是不会有任何效果的,你需要自己修改网站服务的配置文件来将 ssl 证书部署到线上
请点击此处查看ssl证书的部署教程
这些就是全部内容了!感谢你阅读这篇文章
给 Docker Fans 的一点小参考
好好好,现在我知道你要用Docker了
你可以参考 acme.sh官方的Docker文档
我不太喜欢他的文档,因为要挂载docker.sock
文件,这可能对安全性造成影响
(Docker = Root)
并且如果你要同时给多个容器部署(好像可以?)会有点麻烦
因此,这是我的解决方案,支持在install-cert
之后在 Docker 宿主机上执行你希望的命令
按照我的懒人习惯,可能会在之后写一个自动部署脚本,期待吧
部署 acme-reloader
这里有好几个文件需要你下载并解压
wget https://ftp.esaps.net/dockersh/acme.sh/acme-reloader.tar.gz
tar xzvf acme-reloader.tar.gz
解压下来之后的文件目录长这样
acme-reloader
|- ssl/
| |-
|- config/
| |-
|- acme-reloader/
| |-
|- acme-reloader-host.service
|- acme-reloader-host.sh
|- acme-reloader.sh
|- docker-compose.yml
正常来说,我们只需要进入acme-reloader
目录并运行docker compose up -d
即可启动acme.sh的容器
怎样在不挂载 docker.sock 的情况下重载 Docker 容器
改个文件先
如果你使用网站根目录验证的话,你需要挂载你的网站目录到容器里面
请找到我们的acme-reloader-host.sh
文件并找到这个片段并按照注释修改文件(已将注释翻译)
function restart_command() {
#请在这里放下你在证书申请完成之后需要在docker宿主机上执行的命令
#请类似于这样的格式书写:restart_with "需要执行的命令",一行一条
#这样才可以在本目录下acme-reloader.log查找到命令执行异常时的日志
restart_with "YOUR_OWN_SH_COMMAND"
#输入完成!请不要更改其他文段并享受你的自动化过程吧 :)
echo "Complete" >> ./socket/acme-reloader.sock
}
找到我们的acme-reloader-host.service
文件并作出以下更改
- 请将
/path/to/acme-reloader-host.sh_directory
替换为acme-reloader目录
的绝对路径 - 请将
/path/acme-reloader-host.sh
替换为到acme-reloader-host.sh
的绝对路径
然后,把这个文件复制到/usr/lib/systemd/system/
目录里面
(请注意,如果你的 Linux 发行版过早,可能使用的是 init.d 而非 systemd ,这个时候我相信你可以自己写一个服务脚本的)(确信)
(算了不那么欠扁到时候我再写一个吧)
acme-reloader-host,启动!
执行命令来让 systemd 操控我们的acme-reloader
吧
systemctl daemon-reload #重载配置文件,必须执行一次,否则可能提示找不到acme-reloader-host.service
systemctl start acme-reloader-host.service #启动acme-reloader-host
systemctl stop acme-reloader-host.service #关闭acme-reloader-host
systemctl restart acme-reloader-host.service #重启acme-reloader-host
systemctl status acme-reloader-host.service #查看acme-reloader-host运行状态
在接下来的操纵前,你需要先启动acme-reloader-host
服务,否则你可能在 acme.sh 执行重启命令时收到错误信息
还需要一点操作
将acme-reloader.sh
文件复制到acme.sh
容器的根目录(注意替换为你自己的容器名称,如果使用了我的 docker-compose.yml 可以不用更改)
docker cp ./acme-reloader.sh acme.sh:/
然后,像本文前面内容一样申请证书吧~
sudo docker exec -it acme.sh acme.sh
由于我们是在 Docker 容器里面运行,所以要用这种繁琐的方式来替换前文的爽快 acme.sh 命令
如果你怕麻烦,你可以执行这条命令来简便一点
alias acme.sh="sudo docker exec -it acme.sh acme.sh"
你也可以直接进入 acme.sh 容器来操作
sudo docker exec -it acme.sh ash
接下来我会使用 acme.sh 命令直接演示
因为我们是直接运行了 Docker 容器,所以我们需要先在CA那边注册一个账号
acme.sh --register-account --server letsencrypt -m myemail@example.com
并且更换acme.sh的默认CA
acme.sh --set-default-ca --server letsencrypt
然后就可以按照上面的内容一样申请证书喽
注意:如果你使用自动 DNS 验证申请的话,最好还是直接进入容器里面先申请一次,让 acme.sh 先保存你的 API 密匙
最后一点点了!
是的,还差安装证书
acme.sh --install-cert -d example.com \
--cert-file /ssl/server.crt \
--key-file /ssl/server.key \
--ca-file /ssl/ca.crt \
--fullchain-file /ssl/fullchain.pem \
--reloadcmd "sh /acme-reloader.sh"
我默认在docker-compose.yml
帮你挂载了/ssl
目录,这个目录 docker-compose.yml 的同级目录下
如果一切正常,你将在docker-compose.yml
同级目录下的./ssl
目录找到你的证书文件
--reloadcmd
必须改为sh /acme-reloader.sh
,这样子我们才可以通知宿主机来执行重载命令
如果你没有在宿主机上启动acme-reloader-host服务,将会提示
Host error: Unable to connect to host.
此时需要你先启动 acme-reloader-host 服务再重新安装证书
还有,acme-reloader-host 服务的日志在 acme-reloader-host.sh 同级目录下,如果重载失败了你可以查看是哪条命令出错了喵
完成~!享受你的证书自动化吧!
(多嘴一句,你需要自己修改网站服务配置文件来部署,具体看这里)
#!trpst#trp-gettext data-trpgettextoriginal=134#!trpen#Leave a Reply#!trpst#/trp-gettext#!trpen#