acme.sh获取免费自动续期的SSL证书

安装acme.sh

根据情况选择下面的命令进行安装

1
2
3
4
5
6
7
curl https://get.acme.sh | sh -s email=email@example.com

# 实测邮箱是可以省略的也就是
curl https://get.acme.sh | sh

# 或者使用国内镜像:
curl https://gitcode.net/cert/cn-acme.sh/-/raw/master/install.sh?inline=false | sh

安装完成后在命令行执行acme.sh测试是否安装成功(可能需要重新连接终端)

可以参考的官方文档

生成证书

acme.sh 实现了 acme 协议支持的所有验证协议. 一般有两种方式验证: http 和 dns 验证.

1. http 方式需要在你的网站根目录下放置一个文件, 来验证你的域名所有权,完成验证. 然后就可以生成证书了.

1
acme.sh  --issue  -d mydomain.com -d www.mydomain.com  --webroot  /home/wwwroot/mydomain.com/

只需要指定域名, 并指定域名所在的网站根目录. acme.sh 会全自动的生成验证文件, 并放到网站的根目录, 然后自动完成验证. 最后会聪明的删除验证文件. 整个过程没有任何副作用.

如果你用的 apache服务器, acme.sh 还可以智能的从 apache的配置中自动完成验证, 你不需要指定网站根目录:

1
acme.sh --issue -d mydomain.com --apache

如果你用的 nginx服务器, 或者反代, acme.sh 还可以智能的从 nginx的配置中自动完成验证, 你不需要指定网站根目录:

1
acme.sh --issue -d mydomain.com --nginx

注意, 无论是 apache 还是 nginx 模式, acme.sh在完成验证之后, 会恢复到之前的状态, 都不会私自更改你本身的配置. 好处是你不用担心配置被搞坏, 也有一个缺点, 你需要自己配置 ssl 的配置, 否则只能成功生成证书, 你的网站还是无法访问https. 但是为了安全, 你还是自己手动改配置吧.

如果你还没有运行任何 web 服务, 80 端口是空闲的, 那么 acme.sh 还能假装自己是一个webserver, 临时听在80 端口, 完成验证:

1
acme.sh --issue -d mydomain.com --standalone

更高级的用法请参考

2. 手动 dns 方式, 手动在域名上添加一条 txt 解析记录, 验证域名所有权.

这种方式的好处是, 你不需要任何服务器, 不需要任何公网 ip, 只需要 dns 的解析记录即可完成验证. 坏处是,如果不同时配置 Automatic DNS API,使用这种方式 acme.sh 将无法自动更新证书,每次都需要手动再次重新解析验证域名所有权。

1
2
acme.sh --issue --dns -d mydomain.com \
--yes-I-know-dns-manual-mode-enough-go-ahead-please

然后, acme.sh 会生成相应的解析记录显示出来, 你只需要在你的域名管理面板中添加这条 txt 记录即可.

等待解析完成之后, 重新生成证书:

1
2
acme.sh --renew -d mydomain.com \
--yes-I-know-dns-manual-mode-enough-go-ahead-please

注意第二次这里用的是 --renew

3. 自动dns方式

dns 方式的真正强大之处在于可以使用域名解析商提供的 api 自动添加 txt 记录完成验证.

acme.sh 目前支持 cloudflare, dnspod, cloudxns, godaddy 以及 ovh 等数十种解析商的自动集成.

以 dnspod 为例, 你需要先登录到 dnspod 账号, 生成你的 api id 和 api key, 都是免费的. 然后:

1
2
3
export DP_Id="1234"
export DP_Key="sADDsdasdgdsf"
acme.sh --issue --dns dns_dp -d aa.com -d www.aa.com

证书就会自动生成了. 这里给出的 api id 和 api key 会被自动记录下来, 将来你在使用 dnspod api 的时候, 就不需要再次指定了. 直接生成就好了:

1
acme.sh --issue -d mydomain2.com --dns dns_dp

注意:腾讯云注册的域名目前全部划归到DNSPod名下。或者说DNSPod现在归属腾讯

  1. 务必注意变量大小写,比如 DP_Id 而不是 DP_ID
  2. 在使用DNSPod时注意需要的是DNSPod的Token而不是腾讯云的API密钥

DNSPod Token获取路径:

  1. 登录https://www.dnspod.cn/
  2. 点击头像导航栏位置,然后点击 API密钥 ,或者可以直接打开:https://console.dnspod.cn/account/token/apikey
  3. 该页面默认显示的是腾讯云的API密钥,点击 DNSPod Token 生成管理 DNSPod Token。或者你也可以直接打开:https://console.dnspod.cn/account/token/token

下面是阿里云的示例:

首先登录阿里云账号获取 RAM API key :https://ram.console.aliyun.com/users

1
2
3
export Ali_Key="sdfsdfsdfljlbjkljlkjsdfoiwje"
export Ali_Secret="jlsdflanljkljlfdsaklkjflsa"
# 同样注意大小写

Ok, 申请一个证书:

1
./acme.sh --issue --dns dns_ali -d example.com -d www.example.com

Ali_KeyAli_Secret 会存储在 ~/.acme.sh/account.conf 并在需要的时候再次使用

多嘴一句,注意阿里云AccessKey的权限问题,主账号生成的都是有全部权限的。对于生产环境,强烈建议使用子账号生成低权限的AccessKey

支持的域名商列表以及更详细的 api 用法

安装证书

前面证书生成以后, 接下来需要把证书 copy 到真正需要用它的地方.

注意, 默认生成的证书都放在安装目录下: ~/.acme.sh/, 请不要直接使用此目录下的文件, 例如: 不要直接让 nginx/apache 的配置文件使用这下面的文件. 这里面的文件都是内部使用, 而且目录结构可能会变化.

正确的使用方法是使用 --install-cert 命令,并指定目标位置, 然后证书文件会被copy到相应的位置, 例如:

Apache example:

1
2
3
4
5
acme.sh --install-cert -d example.com \
--cert-file /path/to/certfile/in/apache/cert.pem \
--key-file /path/to/keyfile/in/apache/key.pem \
--fullchain-file /path/to/fullchain/certfile/apache/fullchain.pem \
--reloadcmd "service apache2 force-reload"

Nginx example:

1
2
3
4
acme.sh --install-cert -d example.com \
--key-file /path/to/keyfile/in/nginx/key.pem \
--fullchain-file /path/to/fullchain/nginx/cert.pem \
--reloadcmd "service nginx force-reload"

(一个小提醒, 这里用的是 service nginx force-reload, 不是 service nginx reload, 据测试, reload 并不会重新加载证书, 所以用的 force-reload)

对于使用 systemctl进行服务管理的,建议直接 systemctl restart nginx

--reloadcmd这个参数就是一个命令,可以是任何命令,比如下面是我使用的安装命令:

1
2
3
4
acme.sh --install-cert -d xgqyq.com \
--key-file /root/nginx/conf.d/nginx/xgqyq.com.key \
--fullchain-file /root/nginx/conf.d/nginx/xgqyq.com.crt \
--reloadcmd "docker restart nginx"

Nginx 的配置 ssl_certificate 使用 /etc/nginx/ssl/fullchain.cer ,而非 /etc/nginx/ssl/<domain>.cer ,否则 SSL Labs 的测试会报 Chain issues Incomplete 错误。

上一步的生成证书会生成key、证书以及证书链,对于nginx来说ssl_certificate是可以使用证书和证书链的。

证书以及证书链的格式是不那么重要的,你可以不用关心生成的格式,直接指定nginx中配置的格式就可以。会自动转换格式

--install-cert命令可以携带很多参数, 来指定目标文件. 并且可以指定 reloadcmd, 当证书更新以后, reloadcmd会被自动调用,让服务器生效.

详细参数请参考https://github.com/Neilpang/acme.sh#3-install-the-issued-cert-to-apachenginx-etc

值得注意的是, 这里指定的所有参数都会被自动记录下来, 并在将来证书自动更新以后, 被再次自动调用.

证书更新

目前证书在 60 天以后会自动更新, 你无需任何操作. 今后有可能会缩短这个时间, 不过都是自动的, 你不用关心.

请确保 cronjob 正确安装, 看起来是类似这样的:

1
2
3
crontab  -l

56 * * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

或者你也可以手动更新:

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

关于修改ReloadCmd

目前修改ReloadCmd没有专门的命令,可以通过重新安装证书来实现修改reloadCmd的目的。 此外,安装证书后,相关信息是保存在~/.acme.sh/example.com/example.conf文件下的,内容就是acme.sh --info -d example.com输出的信息,不过ReloadCmd在文件中使用了Base64编码。理论上可以通过直接修改该文件来修改ReloadCmd,且修改时,无需Base64编码,直接写命令原文acme.sh也可以识别。 不过,example.conf文件的位置和内容格式以后可能会改变!example.conf一直都是内部使用, 后面有可能会改为用 sqlite 或者mysql 格式存储. 所以一般不建议自己修改。

更新 acme.sh

目前由于 acme 协议和 letsencrypt CA 都在频繁的更新, 因此 acme.sh 也经常更新以保持同步.

升级 acme.sh 到最新版 :

1
acme.sh --upgrade

如果你不想手动升级, 可以开启自动升级:

1
acme.sh  --upgrade  --auto-upgrade

之后, acme.sh 就会自动保持更新了.

你也可以随时关闭自动更新:

1
acme.sh --upgrade  --auto-upgrade  0

参考资料

acme.sh项目的WIKI

acme.sh实现免费自动续期的https

FreeSSL证书自动化

acme.sh项目的中文ReadMe


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!