acme.sh踩坑:记一次坑爹的https证书申请经历

Published on 2021-03-30 10:53 in 分类: 软件 with 狂盗一枝梅
分类: 软件

acme.sh踩坑:记一次坑爹的https证书申请经历

我的博客网站申请的免费的https证书快到期了,之前使用的是 https://zerossl.com/ 申请的免费证书,没想到用了几次之后就不给用了,到了最大使用免费次数云云。。

image-20210329160535915

之后,我找到了acme.sh这个牛逼的工具,这个工具封装了实现了 acme 协议, 可以从 letsencrypt 生成免费的证书,而且还支持自动续签操作。

acme.sh是个开源项目,github地址:https://github.com/acmesh-official/acme.sh ,中文使用说明:https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E

关于具体使用方式,在官方的中文文档中已经做了详细的说明,先过一下基本的使用流程

一、基本使用

1、安装acme.sh

安装非常简单,一个命令就可以了

curl https://get.acme.sh | sh -s email=my@example.com

安装完成之后,在用户根目录,就会有了一个acme的安装目录~/.acme.sh/

同时,它会创建一个crontab定时任务,每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新, 则会自动更新证书.

2、申请证书

接下来在nginx环境下使用阿里云dns api的方式自动申请证书(我的是阿里云申请的域名)。

第一步:去阿里云控制台创建access key和access secret

image-20241104220405929

进去创建即可,记住access key和access secret,然后修改~/.bashrc ,添加记录

export Ali_Key="<key>"
export Ali_Secret="<secret>"

最后退出bash,重新进入,让环境变量生效。

第二步:申请证书

先用命令

acme.sh --set-default-ca --server letsencrypt

把ca服务器改成letsencrypt,这样可以加快申请速度。

然后执行如下命令

acme.sh --issue --dns dns_ali -d <your domain> --nginx --force

第三步:安装证书

证书申请成功后默认在~/.acme目录下,以域名_ecc为名的目录

.
├── backup
│   ├── fullchain.bak
│   ├── key.bak
│   └── waline.kdyzm.cn.nginx.conf
├── ca.cer
├── fullchain.cer
├── waline.kdyzm.cn.cer
├── waline.kdyzm.cn.conf
├── waline.kdyzm.cn.csr
├── waline.kdyzm.cn.csr.conf
└── waline.kdyzm.cn.key

使用命令

acme.sh --install-cert -d <your domain> \
--key-file       /自定义目录/key.pem  \
--fullchain-file /自定义目录/cert.pem \
--reloadcmd     "service nginx force-reload"

安装到指定的目录,接下来nginx配置ssl要用到。

3、配置niginx

配置nginx的方式如下

server{
        listen 4432;
        server_name <your domain>;
        ssl on;
    	# 我将证书安装到了/etc/nginx/ssl/waline目录
        ssl_certificate  /etc/nginx/ssl/waline/cert.pem;
        ssl_certificate_key     /etc/nginx/ssl/waline/key.pem;
        ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
        ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
        ssl_prefer_server_ciphers on;
        ssl_session_cache shared:SSL:10m;
        ssl_session_timeout 10m;
        add_header Strict-Transport-Security "max-age=31536000";

        location /{
                    proxy_pass   http://127.0.0.1:8360;
                    proxy_set_header Host $host;
                    proxy_set_header X-Real-IP $remote_addr;
                    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                    proxy_set_header X-Forwarded-Proto $scheme;
                    proxy_set_header REMOTE-HOST $remote_addr;
                    add_header X-Cache $upstream_cache_status;
                    # cache
                    add_header Cache-Control no-cache;
                    expires 12h;
                }
        }

之后使用命令

service nginx force-reload

重启nginx,之后就大工告成了。

4、常用命令总结

查看证书命令:

 ~/.acme.sh/acme.sh --info -d waline.kdyzm.cn

手动更新证书的命令

 ~/.acme.sh/acme.sh --renew-all --force

查看crontab命令

crontab -l

二、容器化改造

接下来是我将acme.sh安装到docker容器中的经历,现在看起来很蠢,有很多问题,但是毕竟也是经验,暂且保存下来吧。

1.初始脚本和遇到的问题

我使用nginx作为博客网关并做请求转发,但是这个nginx是用docker部署的,博客的mysql、nginx以及后端的java程序都是使用docker-compose做的编排。

nginx是使用官方1.16版本的镜像直接创建的容器,这就意味着如果想实现https证书自动续签功能,就要把acme.sh安装到容器内。

nginx容器内运行的应该是debian linux,我写了个脚本实现安装

#!/bin/bash
  
mv /etc/apt/sources.list /etc/apt/sources.list.bak && \
echo "deb http://mirrors.163.com/debian/ buster main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian/ buster-updates main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian/ buster-backports main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib" >>/etc/apt/sources.list

export DEBIAN_FRONTEND=noninteractive
apt-get update &&
    apt-get -o Dpkg::Options::="--force-confold" upgrade -q -y --force-yes &&
    apt-get -o Dpkg::Options::="--force-confold" dist-upgrade -q -y --force-yes

apt -y update
apt-get install -y gnupg2
apt-get install -y ca-certificates
apt install -y --no-install-recommends curl
apt-get install -y cron
apt-get install -y socat
apt-get install -y vim

mkdir /usr/local/etc/blog

blue(){
    echo -e "\033[34m\033[01m$1\033[0m"
}
green(){
    echo -e "\033[32m\033[01m$1\033[0m"
}
red(){
    echo -e "\033[31m\033[01m$1\033[0m"
}

cd /usr/sbin

your_domain="blog.kdyzm.cn"
        green " "
        green " "
        green "=========================================="
		blue "获取到你的域名为 $your_domain"
        green "=========================================="
        sleep 3s
    green " "
        green " "
        green "=========================================="
        blue "安装acme.sh 并开始签发证书"
        green "=========================================="
        sleep 3s

/usr/sbin/nginx -s reload

        curl https://get.acme.sh | sh
        ~/.acme.sh/acme.sh --issue -d $your_domain --nginx
        ~/.acme.sh/acme.sh --installcert -d $your_domain --key-file /usr/local/etc/blog/private.key --fullchain-file /usr/local/etc/blog/cert.crt
        ~/.acme.sh/acme.sh --upgrade --auto-upgrade
        chmod -R 755 /usr/local/etc/blog

if test -s /usr/local/etc/blog/cert.crt; then

/usr/sbin/nginx -s reload

        green "=========================================="
                blue "检测到证书已经正常签发"
        green "=========================================="
else
        green "=========================================="
                red "证书签发失败,请重新尝试"
        green "=========================================="
fi

这个脚本修改过很多次,理论上是没有问题的,但是最后却卡在了github下载上,死活下载不动,试过修改dns的方法,但是没有生效

github在大陆访问极其不友好,使用curl下载东西肯定超时

2.修改脚本

仔细看看官网,除了在线安装的方法之外,还有离线安装解决方案,那就是git clone 项目之后,直接执行acme.sh脚本,这时候就不会自动到github下载了,修改之后的脚本

#!/bin/bash
  
mv /etc/apt/sources.list /etc/apt/sources.list.bak && \
echo "deb http://mirrors.163.com/debian/ buster main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian/ buster-updates main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian/ buster-backports main non-free contrib" >>/etc/apt/sources.list
echo "deb http://mirrors.163.com/debian-security/ buster/updates main non-free contrib" >>/etc/apt/sources.list

export DEBIAN_FRONTEND=noninteractive
apt-get update &&
    apt-get -o Dpkg::Options::="--force-confold" upgrade -q -y --force-yes &&
    apt-get -o Dpkg::Options::="--force-confold" dist-upgrade -q -y --force-yes

apt -y update
apt-get install -y gnupg2
apt-get install -y ca-certificates
apt-get install -y curl
apt-get install -y cron
apt-get install -y socat
apt-get install -y vim

mkdir /usr/local/etc/blog
blue(){
    echo -e "\033[34m\033[01m$1\033[0m"
}
green(){
    echo -e "\033[32m\033[01m$1\033[0m"
}
red(){
    echo -e "\033[31m\033[01m$1\033[0m"
}

cd /usr/sbin

your_domain="blog.kdyzm.cn"
        green " "
        green " "
        green "=========================================="
                        blue "获取到你的域名为 $your_domain"
        green "=========================================="
        sleep 3s
    green " "
        green " "
        green "=========================================="
        blue "       安装acme.sh 并开始签发证书"
        green "=========================================="
        sleep 3s

/usr/sbin/nginx -s reload

#        curl https://get.acme.sh | sh
        cd /acme
        chmod a+x ./acme.sh
        ./acme.sh --install -m kdyzm@foxmail.com
        ~/.acme.sh/acme.sh --issue -d $your_domain --nginx
        ~/.acme.sh/acme.sh --installcert -d $your_domain --key-file /usr/local/etc/blog/private.key --fullchain-file /usr/local/etc/blog/cert.crt
        #~/.acme.sh/acme.sh --upgrade --auto-upgrade
        chmod -R 755 /usr/local/etc/blog

if test -s /usr/local/etc/blog/cert.crt; then

/usr/sbin/nginx -s reload

        green "=========================================="
                blue "检测到证书已经正常签发"
        green "=========================================="
else
        green "=========================================="
                red "证书签发失败,请重新尝试"
        green "=========================================="
fi

我将curl https://get.acme.sh | sh这行代码注释掉,使用了本地安装的方法,但是这时候需要手动将acme.sh代码拉下来并拷贝到容器;同时,要关闭自动更新,因为自动更新还会下载github上的代码。

3.修改nginx配置

证书申请完成之后生成了两个关键文件在/usr/local/etc/blog文件夹:private.key以及cert.crt,nginx的https配置需要这两个文件,

server {
        listen 443;
        ssl on;
        server_name  blog.kdyzm.cn;
        ssl_certificate  /usr/local/etc/blog/cert.crt;
        ssl_certificate_key /usr/local/etc/blog/private.key;
        location / {
            proxy_pass   http://....;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-Proto https;
            client_max_body_size  20m;
        }
    }

提前准备好这个文件,执行完成脚本之后会自动重启nginx,该文件中的配置会自动生效。

4.注意事项

  • /usr/local/etc/blog/private.key 和 /usr/local/etc/blog/cert.crt 在未正式申请证书之前就要存在,否则nginx会检测不到有效证书而陷入无限重启中
  • 容器全部启动之后进入nginx容器(使用命令 docker exec -it 容器id /bin/bash),执行申请证书脚本

#acme #https
目录
复制 复制成功