ACME 是一个自动管理证书的程序。 rfc8555 是 ACME 的 rfc 。
ACME
Automatic Certificate Management Environment
自动 证书 管理 环境
ACME 有很多种实现,这篇文章描述的是 acme.sh 的使用。
acme.sh 的 GitHub 仓库地址
https://github.com/acmesh-official/acme.sh
acme.sh 的文档
https://github.com/acmesh-official/acme.sh/wiki
中文说明
https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E
https://github.com/acmesh-official/acme.sh/wiki/Blogs-and-tutorials#%E4%B8%AD%E6%96%87
直接下载安装
curl https://get.acme.sh | sh -s email=my@example.com
curl https://raw.githubusercontent.com/acmesh-official/acme.sh/master/acme.sh | sh -s -- --install-online -m my@example.com
从源码安装
git clone --depth 1 https://github.com/acmesh-official/acme.sh.git
cd acme.sh
./acme.sh --install -m my@example.com
安装完后把 .acme.sh 文件夹复制到用户的根目录下,类似这样的路径
~/.acme.sh/
/root/.acme.sh/
为 acme.sh 创建一个别名
alias acme.sh=~/.acme.sh/acme.sh
其实把安装后的目录复制到用户的根目录和创建别名都不是必须的,但为了贴合文档的教程和方便使用,最好还是这样做
运行这句命令申请证书, 运行这句命令时,http服务需要已经启用,并且是监听 80 端口的, 注意修改域名和站点根目录的路径
acme.sh --issue -d www.example.com --webroot /home/wwwroot/example.com/
如果加上 --standalone 参数, acme.sh 能临时运行一个 webserver, 临时听在80 端口,但这是使用 socat 实现的,所以要先安装好 socat
acme.sh --issue -d www.example.com --webroot /home/wwwroot/example.com/ --standalone
申请证书命令运行后会输出证书生成的位置,这个位置通常是
~/.acme.sh/www.example.com_ecc/cert.pem
~/.acme.sh/www.example.com_ecc/www.example.com.key
~/.acme.sh/www.example.com_ecc/fullchain.cer
上面的命令是使用 HTTP 验证, DNS 验证因为笔者没有用到就不记录了
acme.sh --install-cert -d www.example.com \
--cert-file /c/nginx/crt/www.example.com/cert.pem \
--key-file /c/nginx/crt/www.example.com/www.example.com.key \
--fullchain-file /c/nginx/crt/www.example.com/fullchain.cer \
--reloadcmd "service nginx force-reload"
要先运行过安装证书的命令才能使用续签证书的命令。 如果没有,那么要重新申请一次证书,然后把证书复制到对应的目录里。 多数情况下,续签证书的命令会加到定时任务里。
一般的命令
~/.acme.sh/acme.sh --cron --home "/root/.acme.sh" > /dev/null
# windows 环境下要写成这样
~/.acme.sh/acme.sh --cron --home "/c/Users/Administrator/.acme.sh" > /dev/nul
# --home 是 acme.sh 的安装路径,要写成绝对路径
写成 cron 表达式
0 2 * * * /bin/bash /root/.acme.sh/acme.sh --cron --home "/root/.acme.sh" > /dev/null
这个命令除了用于续签证书外,还用于自动更新
查看全部证书
acme.sh --list
<!--
产看全部证书,包括已过时的
```
acme.sh --list-archive
```
-->
查看已安装证书的信息
acme.sh --info -d www.example.com
删除证书
acme.sh --remove -d www.example.com
更新
acme.sh --upgrade
开启自动更新
acme.sh --upgrade --auto-upgrade
关闭自动更新
acme.sh --upgrade --auto-upgrade 0
卸载 acme.sh
acme.sh --uninstall
acme.sh 文档里关于 Windows 环境的描述
https://github.com/acmesh-official/acme.sh/wiki#4-how-to-run-on-windows-with-cygwin-or-git-bash
自动续签证书的定时任务可以使用 windows 计划任务,但这样的写法,任务运行时会有一个黑框弹出来 (笔者试了很多方法依然无法隐藏这个黑框,在服务器里每晚运行一次的话应该没关系的吧,即使有黑框也是一闪而过)
Register-ScheduledTask -TaskName "acme_cron" -AsJob -Trigger (New-ScheduledTaskTrigger -Daily -At "2:00 AM") -Action (New-ScheduledTaskAction -Execute "PowerShell" -Argument "-Nolog -NonInteractive -WindowStyle Hidden -Command `"C:\Users\a\Git\usr\bin\bash.exe -l /c/Users/a/.acme.sh/acme.sh --cron --home /c/Users/a/.acme.sh`"")
似乎可以这样安装 计划任务 ,即使在 windows 环境里,只要在 cygwin 中运行,一样是有效的
acme.sh --install-cronjob
删除定时任务
acme.sh --uninstall-cronjob
<!-- 从源码里看,似乎只要运行了 acme.sh --install 就会自动新建定时任务了,除非指定了 --no-cron 参数 -->
假设已经安装好 acme.sh 和 nginx
acme.sh --issue -d www.example.com --webroot $(pwd)
在 nginx 的安装目录里新建一个名为 restart.ps1 的文件并写入以下内容,这个脚本主要是用于重启 nginx 的,要注意 powershell 的执行策略
# 切换到批处理文件所在的目录
Set-Location $PSScriptRoot
# 显示批处理文件所在的目录
Write-Output $PSScriptRoot
# 停止 nginx 服务
./nginx.exe -s quit
# 等待 6 秒
Start-Sleep -Seconds 6
# 强制结束 nginx 进程及其子进程
Get-Process -Name nginx | Stop-Process -Force
# 测试 nginx 配置文件
./nginx.exe -T
# 启动 nginx 服务
Start-Process -FilePath powershell -ArgumentList "-NonInteractive", "-command", "./nginx.exe"
acme.sh --install-cert -d www.example.com \
--cert-file /c/Users/a/nginx/crt/www.example.com/cert.pem \
--key-file /c/Users/a/nginx/crt/www.example.com/www.example.com.key \
--fullchain-file /c/Users/a/nginx/crt/www.example.com/fullchain.cer \
--reloadcmd "powershell \"C:\Users\a\nginx\restart.ps1\""
在 nginx 的配置文件里加上这一段
server {
listen 80;
server_name www.example.com;
listen 443 ssl http2;
ssl_certificate ./crt/www.example.com/fullchain.cer;
ssl_certificate_key ./crt/www.example.com/www.example.com.key;
access_log logs/www.example.com.access.log;
error_log logs/www.example.com.error.log;
if ($scheme = 'http') {
return 302 https://$host$request_uri;
}
location / {
root C:/User/a/www.example.com; # 这是站点根目录的路径
index index.html index.htm;
}
}