acme.sh踩坑:记一次坑爹的https证书申请经历
我的博客网站申请的免费的https证书快到期了,之前使用的是 https://zerossl.com/ 申请的免费证书,没想到用了几次之后就不给用了,到了最大使用免费次数云云。。
之后,我找到了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
进去创建即可,记住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),执行申请证书脚本
注意:本文归作者所有,未经作者允许,不得转载