申请acme.sh免费SSL证书

介绍

HTTP(HyperText Transfer Protocol:超文本传输协议)是一种用于分布式、协作式和超媒体信息系统的应用层协议。 简单来说就是一种发布和接收 HTML 页面的方法,被用于在 Web 浏览器和网站服务器之间传递信息。HTTP是明文传输数据,数据都是未加密的安全性差。

HTTPS(Hypertext Transfer Protocol Secure:超文本传输安全协议)是一种透过计算机网络进行安全通信的传输协议。HTTPS 经由 HTTP 进行通信,但利用 SSL/TLS 来加密数据包。HTTPS 开发的主要目的,是提供对网站服务器的身份认证,保护交换数据的隐私与完整性。

如今,互联网基本全都支持HTTPS,因为相比HTTP,HTTPS更加安全,可以防止第三方入侵我们的网站,我们有时候打开一些老一点的HTTP的站点,会自动跳转到别的奇奇怪怪的网站上去,由于HTTP网站安全性不够,如果被一些不法分子劫持,跳转到第三方网站,如果我们使用HTTPS,会放不法分子入侵难度加大,从而可以减少被入侵的机会,让我们网站更加安全。

acme.sh的出现,解决了我们小站的HTTPS问题,acme.sh可以申请免费的SSL/TLS证书,安装在我们的网站上,使我们的网站支持HTTPS,并且安装过程简单,适合我们流量不大的博客。

acme.sh的特点:

  • 一个纯粹用Shell(Unix shell)语言编写的ACME协议客户端。
  • 完整的ACME协议实施。 支持ACME v1和ACME v2 支持ACME v2通配符证书
  • 简单,功能强大且易于使用。你只需要3分钟就可以学习它。
  • Let’s Encrypt免费证书客户端最简单的shell脚本。
  • 纯粹用Shell编写,不依赖于python或官方的Let’s Encrypt客户端。
  • 只需一个脚本即可自动颁发,续订和安装证书。 不需要root/sudoer访问权限。
  • 支持在Docker内使用,支持IPv6

安装acme.sh

官方提供了两种方式安装:

  1. 在线脚本安装
  2. 通过 git 安装

通过执行在线脚本安装:

1
2
3
$ curl https://get.acme.sh | sh
# 或者
$ wget -O - https://get.acme.sh | sh

通过 git 安装:

1
2
3
git clone https://github.com/Neilpang/acme.sh.git
cd ./acme.sh
./acme.sh --install

在安装的过程中,做了 3 件事:

  • 复制 acme.sh 到你的 HOME 目录($HOME):~/.acme.sh/。之后所有生成的证书也会放在这里。
  • 创建别名:acme.sh=~/.acme.sh/acme.sh
  • 创建 cron 每日任务去检查是否有证书需要更新。 如: 0 0 * * * "/home/user/.acme.sh"/acme.sh --cron --home "/home/user/.acme.sh" > /dev/null

创建软链接

类似Windows下的快捷方式,将acme.sh添加到全局,这样无论在哪一个目录下都可以执行该命令。

1
ln -s /root/.acme.sh/acme.sh /usr/local/sbin/acme.sh

选择颁发证书机构

下面的两个证书颁发机构,任意选一个即可。

Let’s Encrypt

截止到2022/11/19日之前,acme.sh已默认为ZeroSSL机构的证书了,该机构的证书需要添加邮箱一下才能申请,如果觉得麻烦,可以改为以前Let's Encrypt机构的证书,如下更改:

1
2
cd /root/.acme.sh
./acme.sh --set-default-ca --server letsencrypt

ZeroSSL

添加邮箱

1
vim /root/.acme.sh/account.conf

account.conf添加你的邮箱,格式如下:

1
ACCOOUNT_EMAIL='1365456@126.com'

申请证书

以下使用web.hikki.site二级域名来测试申请证书。

在申请证书时需要验证你持有该域名的所有权,acme.sh有两种方式来验证,HTTP验证和DNS验证。

域名解析

在申请acme.sh免费证书时,先要在DNS域名商将域名解析到你的IP上,并且这个域名解析到这IP可以正常访问。

解析记录参考:

  • 记录类型:A(将域名指向服务器IPV4地址)
  • 主机记录:web
  • 解析线路:默认
  • 记录值:IP地址
  • TTL:10分钟(默认)

nginx配置

1
2
3
4
5
6
7
8
server {
listen 80;
server_name web.hikki.site;
location / {
root /www/test; #你服务器的博客根目录
index index.html index.htm;
}
}

配置完nginx,检查一下是否有配置错误,使用/usr/local/nginx/sbin/nginx -t测试否是有语法错误,检查没问题之后更新配置/usr/local/nginx/sbin/nginx -s reload

浏览器打开

http://web.hikki.site,看看是否可以正常打开,如果可以就可以开始申请证书了;

申请web.hikki.site证书

可以一起申请多个域名的证书

1
2
acme.sh --issue -d web.hikki.site -d two.hikki.site -w /www/test
# acme.sh --issue -d 域名或者二级域名 -w 网站根目录

在申请结束时,会出现一段绿色的文字就是你证书的存在路径,虽然申请成功了,但我们还需要安装一下证书,这样之后证书到期后才会自动帮我们自动更新证书。

02-服务器~.acme.sh -20221029-437

下面使用常见的域名厂商示例:

创建AccessKey

AccessKey管理--->继续使用AccessKey--->创建AccessKey

03-域名控制台20221029-786

4-RAM 访问控制20221029-659

5-RAM 访问控制-20221029-527

创建完AccessKey后,复制ID和Secret,在服务器导出变量,直接在服务器执行就好了。

1
2
export Ali_Key="sgfiwjedfasSDFSFsdgh"
export Ali_Secret="skddsddiwjedfasSDFSFkljlfdsaklkidhfk"

Ali_Key和 Ali_Secret 会被保存在 ~/.acme.sh/account.conf,需要时会被重复使用

打开Godaddy:https://developer.godaddy.com/keys

创建api key

01-创建key-20230510-231

输入api key的名字(可选)

02-next-20230510-040

复制Key和Secret

Secret只显示一次,你可以先不要退出这个页面,先去服务器执行操作再关闭这个页面,如果没有记录Secret,重新创建一个就好了。

03-复制key-20230510-889

获取到了Key和Secret就可以去服务器添加API了。

然后在命令行导入变量。

1
2
export GD_Key="sgfiwjedfasSDFSFsdgh"
export GD_Secret="skddsddiwjedfasSDFSFkljlfdsaklkidhfk"

GD_Key 和 GD_Secret 会被保存在 ~/.acme.sh/account.conf,需要时会被重复使用

打开Cloudflare API:https://dash.cloudflare.com/profile/api-tokens

获取到了Key和Secret就可以去服务器添加API了。

然后在命令行导入变量。

1
2
export CF_Key="cloudflare 中查看你的 key" 
export CF_Email="你的 cloudflare 邮箱"

CF_Key 和 CF_Email会被保存在 ~/.acme.sh/account.conf,需要时会被重复使用

然后准备签发证书的命令,因为是签发,所以要使用–issue参数;指明使用dns_ali作为验证方式;后面跟着的-d为指定证书中的域名,这里有一点需要注意的:如果证书中只包含泛域名,那么签发出来的证书是没有根域的。所以需要额外添加一个根域

我这里演示的是一起申请两个域名用同一个SSL证书。

注意:以下安装SSL证书禁止使用sudo,必须在管理员权限下才能执行该指令。

1
acme.sh --issue --dns dns_ali -d web.hikki.site -d jenkins.hikki.site

我这里使用阿里云进行申请证书,你如果是使用Godaddy或者其他域名厂商,把dns_ali改为别厂商名,如Godaddy使用dns_gd,cloudflare使用dns_cf

申请过程大概要2-3分钟,申请成功结果如下:

02-服务器~.acme.sh -20221029-437

新建一个文件夹来存放证书

这个存放路径可以根据自己需求来修改(注意:修改该路径,在下面的安装证书的路径也要修改)

1
mkdir -p /usr/local/nginx/conf/cert/web-jenkins.hikki.site/

安装证书

根据自己的需求选择不一样的安装方式

我原本是申请web.hikki.site和jenkins.hikki.site这两个证书的,但证书的名称是web.hikki.site的,所以在安装时,安装证书名使用web.hikki.site

1
2
3
4
acme.sh --install-cert -d web.hikki.site \
--key-file /usr/local/nginx/conf/cert/web-jenkins.hikki.site/key.pem \
--fullchain-file /usr/local/nginx/conf/cert/web-jenkins.hikki.site/cert.pem \
--reloadcmd "/usr/local/nginx/sbin/nginx -s reload"

如果出现--fullchain-file: command not found错误,将以下的\去掉,并且缩成一行就不会报错了

1
acme.sh --install-cert -d web.hikki.site --key-file   /usr/local/nginx/conf/cert/web-jenkins.hikki.site/key.pem   --fullchain-file /usr/local/nginx/conf/cert/web-jenkins.hikki.site/cert.pem --reloadcmd     "/usr/local/nginx/sbin/nginx -s reload"
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"

参数解释:

  • -d:指定要给的域名SSL证书
  • --key-file:key文件存储路径(默认是pem后缀)
  • --fullchain-file:pem文件存储路径(默认是pem后缀)
  • reloadcmd:定时更新证书,也就是60天定时重启nginx更新证书

这里还有一些 hook 功能,请查看帮助 acme.sh -h,如,--renew-hook(每次证书成功更新后执行的命令)等

证书申请结束

到这里证书已经申请完了,下面这一步看你自己的需求是否需要添加反向代理或者其他操作。

强制将http定向到https(可选)

打开nginx的配置文件nginx.conf文件添加如下信息。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
server {
listen 80;
server_name web.hikki.site;
return 301 https://$server_name$request_uri;

}
server {
listen 443 ssl;
server_name web.hikki.site;

ssl_certificate cert/web.hikki.site/cert.pem;
ssl_certificate_key cert/web.hikki.site/key.pem;

location / {
#我这里反向代理使用HTTP连接到twikoo评论,因为twikoo不支持HTTPS
proxy_pass http://127.0.0.1:8000;
}
}

生效nginx

1
2
/usr/local/nginx/sbin/nginx -t # 检查是否有语法错误
/usr/local/nginx/sbin/nginx -s reload # 平滑重启nginx

Let’s Encrypt和ZeroSSL

acme.sh在v3.0后开始默认免费的SSl证书变更为ZeroSSL了,这个ZeroSSL和原来的Let’s Encrypt差不多的,有效期一样是60天,支持泛域名SSL证书。和 Let’s Encrypt 不同的是,ZeroSSL API 没有速率限制,不存在同一 IP 多次申请 SSL 证书被限制的问题,ZeroSSL 还提供了 WEB 界面可在后台管理 SSL 证书,相比 Let’s Encrypt 功能更加丰富。

切换默认SSL服务商

Let’s Encrypt

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

ZeroSSL

申请ZeroSSL需要自己改为自己的ZeroSSL邮箱,不要乱填邮箱,因为zerossl会同步你的数据到邮箱账号上,乱填的话,可能会失败。

1
acme.sh --register-account -m email@126.com --server zerossl
1
acme.sh --set-default-ca --server zerossl

管理acme.sh证书

目前证书在 60 天以后会通过定时任务自动更新, 你无需任何操作。

更新acme.sh 程序

手动更新acme.sh

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

1
acme.sh --upgrade

自动更新acme.sh

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

可以在手动更新和自动更新选其一即可。

取消自动更新

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

更新证书

指定更新某证书

1
acme.sh --renew  -d blog.hikki.site

更新全部SSL证书

1
acme.sh --renew-all

查看当前证书

1
acme.sh --list

吊销证书

当我们不使用某个证书时,我们应该及时吊销证书。

吊销hikki.site证书

1
acme.sh  --remove  -d blog.hikki.site

重新安装自动更新证书cronjob计划任务

安装cronjob计划任务

1
acme.sh --install-cronjob 

删除cronjob计划任务

1
acme.sh --uninstall-cronjob  

查看所有cronjob计划任务

1
crontab -l 

编辑cronjob计划任务

1
crontab -e

可能会遇到的问题

如提示让我们安装socat 依赖,直接安装即可

20-缺少socat依赖20221119-640

1
sudo apt-get install socat

line 2: $‘\r’: command not found

01command not found

错误分析

这个错误问题是因为原始脚本是在window下编写的,然后这个脚本在Linux运行,导致有些字符识别有误造成的,我们只需要将这个文件转换成Linux版就可以了。

我们可以使用dos2unix这个工具来进行转换。

解决问题

安装dos2unix

1
apt install dos2unix
1
yum -y install dos2unix

转换为Linux版

1
dos2unix 文件名

xxx.xxx:Timeout

1
2
[Sat 29 Oct 2022 10:17:20 PM CST] web.hikki.site:Timeout
[Sat 29 Oct 2022 10:17:20 PM CST] Removing DNS records.

21-服务器.acme.sh 20221029-256

这个问题,可能是SSL服务商的问题,这时候换一个SSL服务商就可以了,你如果使用的是Let’s Encrypt,就切换到ZeroSSL,反之一样。

No EAB credentials found for ZeroSSL, let’s get one

意思是没有找到ZeroSSL的EAB凭据,既然是ZeroSSL的问题,那我们直接更改证书颁发机构就好。

21-没有添加邮箱-20221119-710

解决方法

1
/root/.acme.sh/./acme.sh --set-default-ca --server letsencrypt

–fullchain-file: command not found

代码是没有问题的,环境也没有问题,其实是转移\的问题,不要使用转移字符就好了,将代码缩成一行运行就没问题了

22-fullchain-file 找不到20221119-485

SSL证书过期导致浏览器自动拦截该请求

  1. Failed to load response data:No data found for resource with given identifier

  2. Failed to load response data:No content available for preflight request

  3. net::ERR_CERT_DATE_INVALID

以上信息都是因为SSL证书过期导致出现的错误,acme.sh配置let’s encrypt提供的SSL证书,有效期为90天,到期自动更新。

可能应为acme.sh长期未更新,自动更新证书功能失效。

解决方法

更新acme.sh

1
acme.sh --upgrade

更新SSL证书

1
acme.sh --renew  -d domain.com 
1
acme.sh --renew-all

参考资料:

手动更新acme.sh以及let’s encrypt的ssl证书

acme GoDaddy域名解析实现免费SSL证书自动续签