Bpazy / blog

我的博客,欢迎关注和讨论
https://github.com/Bpazy/blog/issues
MIT License
39 stars 2 forks source link

acme.sh 使用记录 #138

Open Bpazy opened 4 years ago

Bpazy commented 4 years ago

这里记录一些我的使用 acme.sh 的方法、内容,比如生成证书、生成多域名、多子域名证书、自动续期等等。

官方安装和使用文档:https://github.com/Neilpang/acme.sh/wiki/说明

HTTP 方式生成证书

该方法生成的证书不支持泛域名。 还有一点,acme.sh 检测的 nginx 配置文件必须位于 /etc/nginx/sites-enabled 下。

acme.sh --issue -d cdn.example.com --nginx

发现的问题

acme.sh 并不能增量的增加子域名,如现在已有 a.example.com 的证书,想要增加 b.example.com,该脚本就会替换现有的 fullchain.cer 文件,从而导致之前的证书失效。 所以想要添加子域名 b.example.com 的话,要同时创建 a.example.com 和 b.example.com,当子域名数量过多的话,就会触发 Let's Encrypt 的速率限制,比较恶心。

DNS 方式生成证书

该方法生成的证书支持泛域名,从长远角度考虑比较方便,笔者最终采用的就是这种方法。

DNS 方式简单来说就是需要你在 DNS 解析上增加一个 TXT 记录,用于表明该域名归属于你。 但这里有个问题:Let's Encrypy 的证书 3 个月后就会过期,难不成每 3 个月都重新手动操作一遍吗?这也违背了 acme.sh 脚本的初衷。所以这里需要利用 DNS 服务商的 API,这样 acme.sh 可以自动的完成这一切。每一家 DNS 的具体配置方式不一致,请自行查阅官方文档:https://github.com/Neilpang/acme.sh/wiki/dnsapi

export CF_Key="***************************"
export CF_Email="******@163.com"
acme.sh --issue --dns dns_cf -d example.com -d *.example.com

安装证书

acme.sh --installcert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/fullchain.cer \
  --reloadcmd "systemctl restart nginx"

注意这里的 reloadcmd 参数,这是 nginx 重启的命令,如果你没有使用 systemd 或者说你是直接用的 nginx 命令,那请修改对应的命令为:

  1. 关闭 nginx
  2. 开启 nginx

因为 nginx -s reload 命令并不能重新加载证书。

怎么避免连续多次失败触发 Rate limit ?

运行 acme.sh 的时候加上参数 --test

触发 Let's Encrpty 的 Rate limit 怎么办

可以删除 ~/.acme.sh 再重新安装操作。

提示 Failed to connect to dns.google port 如何解决?

使用参数 --dnssleep 300acme.sh 默认情况会使用 google dns 来验证是否生效,该参数可以跳过该验证,文档: dnssleep

Bpazy commented 3 years ago

个人用的命令记录:

export Ali_Key="***"
export Ali_Secret="***"

acme.sh --issue --dns dns_ali -d example.com -d *.example.com  -d netmaker.example.com -d *.netmaker.example.com --debug --httpport socks5://127.0.0.1:1080

acme.sh --installcert -d example.com \
  --key-file /etc/nginx/ssl/example.com.key \
  --fullchain-file /etc/nginx/ssl/fullchain.cer \
  --reloadcmd "systemctl restart nginx"

这里有一个细节,申请证书时,指定了多个泛域名,但是将证书复制到 nginx 目录时,仅指定顶级目录即可。

有时候 httpport 不生效,则该行命令应该替换成:

acme.sh --issue --dns dns_ali -d example.com -d *.example.com  -d netmaker.example.com -d *.netmaker.example.com --debug --dnssleep 300
Bpazy commented 2 years ago

acme.sh 自动续约失效

调查后发现,acme.sh 更新证书实际成功了,只是 nginx 并没有重新装载新的证书。上文中也已经提到, reload 参数是无法更新证书的,必须 停止启动

acme.sh 的文档中写的对应命令为: service force-reload nginx 而发生问题时,我的命令为: systemctl force-reload nginx

于是查看了 service 命令对应的配置文件 /etc/init.d/nginx,发现其中是有 force-reload 这个参数的:

... 省略部分无关代码
    reload|force-reload)
        log_daemon_msg "Reloading $DESC configuration" "$NAME"

        # Check configuration before stopping nginx
        #   
        # This is not entirely correct since the on-disk nginx binary
        # may differ from the in-memory one, but that's not common.
        # We prefer to check the configuration and return an error
        # to the administrator.
        if ! test_config; then
            log_end_msg 1 # Configuration error
            exit $?
        fi  

        reload_nginx
        log_end_msg $?
        ;;  
... 省略部分无关代码

reload_nginx() {
    # Function that sends a SIGHUP to the daemon/service
    start-stop-daemon --stop --signal HUP --quiet --pidfile $PID --name $NAME
    return 0
}

再查看 systemctl 对应的配置文件 /lib/systemd/system/nginx.service,其中并没有 force-reload 这种处理:

[Service]
Type=forking
PIDFile=/run/nginx.pid
ExecStartPre=/usr/sbin/nginx -t -q -g 'daemon on; master_process on;'
ExecStart=/usr/sbin/nginx -g 'daemon on; master_process on;'
ExecReload=/usr/sbin/nginx -g 'daemon on; master_process on;' -s reload
ExecStop=-/sbin/start-stop-daemon --quiet --stop --retry QUIT/5 --pidfile /run/nginx.pid
TimeoutStopSec=5
KillMode=mixed

所以只要修改为 systemctl restart nginx 即可,上文中错误的命令也已修改,所以你看到的就是正确的版本。

注意: 不要用 systemctl reload nginx, 它对应的命令为 nginx -s reload, 无法更新证书。

Bpazy commented 2 years ago

acme.sh 开启自动更新

acme.sh  --upgrade  --auto-upgrade
Bpazy commented 2 years ago

Let's Encrypt 泛域名不支持多级

什么意思呢?你申请 *.example.com 的证书,是无法用在 *.b.example.com 上的,所以申请的时候需要修改下脚本,比如上面我的个人脚本里有提到,同时申请泛域名,和子域名的泛域名即可:

acme.sh --issue --dns dns_ali -d example.com -d *.example.com  -d b.example.com -d *.b.example.com --debug --httpport socks://127.0.0.1:10808
Bpazy commented 2 years ago

证书生成后如何修改 reloadcmd?

参考: https://github.com/acmesh-official/acme.sh/issues/2029

通过 acme.sh --installcert 命令来修改。

比如我使用的是:

acme.sh --installcert -d example.com --key-file /etc/nginx/ssl/example.com.key   --fullchain-file /etc/nginx/ssl/fullchain.cer   --reloadcmd "systemctl restart nginx && docker-compose -f /home/ubuntu/derper-docker/docker-compose.yaml up -d --force-recreate"