使用 ACME 申请免费“永久”的 SSL 证书

导语:在互联网时代,网络安全至关重要。HTTPS作为一种安全的网络传输协议,已经成为网站建设的标配。本文将为您介绍如何使用acme.sh工具自动生成Let’s Encrypt证书,并实现自动续期,让您轻松实现网站HTTPS加密。

问题:之前一直用的腾讯云自己提供的免费证书,一般是1年一换,这个都能接受,现在上游证书变动,大多数云服务提供商提供的免费证书有效期只有 90 天,每3个月手动申请,然后替换服务器上的证书文件,这就有点难受了,因此就有了本文。

一、什么是acme.sh?

acme.sh是一款开源的ACME协议客户端,用于自动生成Let’s Encrypt证书。Let’s Encrypt是一个免费的证书颁发机构,旨在推广HTTPS加密普及。acme.sh支持Linux、Windows等多种操作系统,操作简单,易于上手。

二、安装acme.sh

  1. 打开终端,执行以下命令安装acme.sh:
    1
    curl https://get.acme.sh | sh
  2. 更改默认证书
    因为 acme 已经被 ZeroSSL 收购,其默认的证书方式为 ZeroSSL ,但此证书生成时会携带邮箱,因此需要更换为letsencrypt
    1
    acme.sh --set-default-ca  --server  letsencrypt
    安装程序会自动做以下操作:
  • 自动把acme.sh安装到你的 home 的.acme.sh目录下,即~/.acme.sh/
  • 自动创建一个 bash的别名,方便命令行的直接使用: alias acme.sh=~/.acme.sh/acme.sh
  • 自动为你创建 cron 任务, 每天 0:00 点自动检测所有的证书, 如果快过期了, 需要更新,则会自动更新证书。

三、使用acme.sh生成证书

以下以域名example.com为例,介绍如何使用acme.sh生成证书。

  1. 申请泛域名证书

泛域名证书是一种能够为同一个主域名(例如 example.com )下的所有子域名(如 example.com 、resource.example.com 等)提供安全加密的数字证书。能够通过一个单一的证书来保护主域名及其所有子域名的数据传输,使得网站管理者无需为每个子域名分别购买和管理多个 SSL 证书。

通过 acme 申请的证书,可以绑定满足该通配符型规则的任意三级子域名,例如:

1
2
3
4
5
www.example.com
test.example.com
aaaexample.com
bb.example.com
...
  1. 获取 DNS API 参数

acme 提供的泛域名证书只能通过 dns 的形式来做验证,因此我们需要进入域名解析控制台(或者直接使用当前用户的,在腾讯云中,点击右上账户-访问管理-访问密钥-API密钥管理)创建 API ID 和 API Key

  1. 配置环境变量

由于每个平台的环境变量名称是不一样的,因此你需要去acme-dnsapi 网站里找到你平台的变量名。我这里以腾讯云为例,将 key 和 secret 换成上一步创建的即可

1
2
export Tencent_SecretId="SecretId"
export Tencent_SecretKey="SecretKey"
  1. 生成证书

做完上述操作后,我们的准备工作就做完了,可以使用acme.sh脚本来创建证书了。

1
acme.sh --issue --dns dns_ali -d kaisir.cn -d '*.kaisir.cn' --dnssleep 300 --debug
  • dns 用于指定 dns 校验平台,我这里是阿里云
  • 第一个-d是你的网站主域名,第二个是泛域名
  • dnssleep用于等待操作,因为把 txt 添加到后台,解析不一定能做到立刻生效,所以需要延时一下,此处我设置了 300 秒的延时,执行命令的过程会有个等待倒计时。
  • debug开启调试模式,创建过程中会打印详细的日志出来,方便定位错误。

证书生成成功后,默认保存在以下目录:

1
~/.acme.sh/example.com/

四、安装证书

将生成的证书安装到Web服务器上,以下以Nginx为例:

  1. 创建证书目录:

    1
    mkdir -p /etc/nginx/ssl/example.com
  2. 将证书文件复制到证书目录:

    1
    ~/.acme.sh/acme.sh --installcert -d example.com --keypath /etc/nginx/ssl/example.com/example.com.key --fullchainpath /etc/nginx/ssl/example.com/example.com.pem
  3. 修改Nginx配置文件,添加以下内容:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/nginx/ssl/example.com/example.com.pem;
    ssl_certificate_key /etc/nginx/ssl/example.com/example.com.key;

    # 其他配置
    }

  4. 重启Nginx:

    1
    systemctl restart nginx

五、自动续期证书

acme.sh支持自动续期证书,只需执行以下命令:

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

为方便管理,我们可以将自动续期命令添加到定时任务中。编辑crontab文件:

1
crontab -e

添加以下内容:

1
0 0 * * * "/root/.acme.sh"/acme.sh --renew -d example.com --force > /dev/null

上述命令表示每天凌晨执行一次证书续期操作。

六、多服务器安装acme证书

最开始采用A,B服务器都安装acme.sh,但是一直提示错误
最后采用ssh同步文件方式,由A服务器定时同步到B服务器上,记录一下
设置服务器 A 通过 SSH 免密登录到服务器 B,需要在两台服务器上进行一些操作。以下是详细步骤:

配置SSH登陆

服务器 A:

  1. 生成密钥对:

    1
    ssh-keygen -t rsa

    这会生成一个私钥文件 (id_rsa) 和一个公钥文件 (id_rsa.pub)。私钥文件请妥善保管,不要泄露给任何人。

  2. 将公钥文件添加到服务器 B 的_keys 文件:

    • 使用 cat 命令查看公钥文件的内容:

      1
      cat ~/.ssh/id_rsa.pub
    • 使用 ssh-copy-id 命令将公钥复制到服务器 B 的 ~/.ssh/authorized_keys 文件:

      1
      ssh-copy-id user@serverB

      其中 user 是服务器 B 上的用户名。

    • 如果 ssh-copy-id 命令提示需要输入密码,则输入服务器 B 上的密码。

服务器 B:

  1. 确保 ssh 服务正在运行:

    1
    sudo systemctl status ssh

    如果服务未启动,请使用 sudo systemctl start ssh 启动服务。

  2. 检查 ~/.ssh/authorized_keys 文件:

    确保服务器 A 的公钥文件已添加到 ~/.ssh/authorized_keys 文件中。

  3. (可选) 设置 PermitRootLogin:

    如果需要作为 root 用户登录服务器 B,请修改 /etc/ssh/sshd_config 文件,将 PermitRootLogin 设置为 yes

    • 注意: 允许 root 用户登录存在安全风险,请谨慎考虑。

测试连接:

  • 从服务器 A 连接到服务器 B:

    1
    ssh user@serverB

    如果连接成功,则表示 SSH 免密登录已经配置完成。

配置同步脚本

在 Linux 系统中,你可以使用 rsync 命令来定时同步文件。rsync 是一个强大的文件同步工具,可以通过 SSH 连接来安全地同步文件。

以下是在服务器 A 上生成证书后,定时将文件同步到服务器 B 并重载 Nginx 的简要步骤:

  1. 设置 SSH 免密登录

    在服务器 A 上,确保你可以通过 SSH 免密登录到服务器 B。这样可以让 rsync 在没有人工干预的情况下自动进行文件同步。

  2. 编写同步脚本

    在服务器 A 上创建一个同步脚本,比如 sync_cert.sh,内容类似下面这样:

    1
    2
    3
    #!/bin/bash
    rsync -avz -e ssh /path/to/certificate/files/ user@serverB:/path/to/destination/
    ssh user@serverB "sudo systemctl reload nginx"

    这个脚本使用 rsync 命令将证书文件同步到服务器 B 的指定目录,并在服务器 B 上通过 SSH 执行重载 Nginx 的命令。

  3. 设置定时任务

    在服务器 A 上使用 crontab 来设置定时任务,比如每天凌晨 3 点执行一次同步脚本:

    1
    0 3 * * * /path/to/sync_cert.sh

    这会在每天的凌晨 3 点执行 sync_cert.sh 脚本,将证书文件同步到服务器 B 并重载 Nginx。

这样,当服务器 A 上的证书定时重新生成时,同步脚本会自动将新证书同步到服务器 B,并重载 Nginx 以应用新证书。

总结:通过本文的介绍,相信您已经掌握了使用acme.sh自动生成证书及自动续期的方法。赶紧为您的网站启用HTTPS加密,提高网络安全吧!