之前我一直使用腾讯云的免费域名证书(TrustAsia SSL 证书),有效期 1 年。也就是每年更新一次,不算麻烦。但是近期腾讯云发公告说,免费证书的有效期缩短到 3 个月。这就会很麻烦,需要频繁地更新证书,因此我放弃了,改为使用 acme.sh 这个工具来自动申请免费证书。
以下是具体教程
准备工作
服务器 IP 地址:124.201.26.242(后称之为“目标服务器”)
操作系统:CentOS Stream 8(这个操作系统不适合用到生产环境,可考虑改为与 CentOS 完全兼容的 Rocky Linux)
待申请证书的域名:xxx.example-domain.com
邮箱:eric@example-domain.com
Web 服务软件:Nginx 1.14.1
注意:上面涉及到安全和隐私的信息,均为虚构,不是真实信息,操作时请替换为你的信息。
域名解析
到你所在的域名管理系统的后台,添加一条域名解析,将上面的域名解析到目标服务器的 IP 地址。
运行 Web 服务
给 Nginx 增加一个新的站点配置文件,将 root 替换为你的项目 web 目录
server {
listen 80;
server_name xxx.example-domain.com;
root /home/ericling/projects/my-test-project/web;
index index.html;
}
测试一下,看配置文件是否正确,如果看到以下两行提示,表示配置正确
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
执行以下命令,让配置生效
sudo nginx -s reload
顺利的话,此时可以通过上述域名打开页面。(注意地址栏,一定要使用 http 协议,因为证书尚未准备好)
但可能会得到一个 403 Forbidden 或者 404 Not Found 的错误页面,因为项目 web 目录中没有 index.html 文件。这是正常的,继续后面步骤。
运行 Web 服务的目的是,让证书颁发机构可以通过网络访问到该域名,以验证你拥有该域名的管理权。
安装 acme.sh 程序
使用 root 账号,执行以下命令
curl https://get.acme.sh | sh -s email=eric@example-domain.com
注意:将上面的邮箱替换为你自己的,后面会自动使用该邮箱向证书颁发机构注册账号。
出现以下提示,说明安装成功
[Sat Jul 27 16:49:38 CST 2024] Installing from online archive.
[Sat Jul 27 16:49:38 CST 2024] Downloading https://github.com/acmesh-official/acme.sh/archive/master.tar.gz
[Sat Jul 27 16:49:40 CST 2024] Extracting master.tar.gz
[Sat Jul 27 16:49:40 CST 2024] It is recommended to install socat first.
[Sat Jul 27 16:49:40 CST 2024] We use socat for the standalone server, which is used for standalone mode.
[Sat Jul 27 16:49:40 CST 2024] If you don't want to use standalone mode, you may ignore this warning.
[Sat Jul 27 16:49:40 CST 2024] Installing to /home/root/.acme.sh
[Sat Jul 27 16:49:40 CST 2024] Installed to /home/root/.acme.sh/acme.sh
[Sat Jul 27 16:49:40 CST 2024] Installing alias to '/home/root/.bashrc'
[Sat Jul 27 16:49:40 CST 2024] Close and reopen your terminal to start using acme.sh
[Sat Jul 27 16:49:40 CST 2024] Installing cron job
no crontab for root
no crontab for root
[Sat Jul 27 16:49:40 CST 2024] bash has been found. Changing the shebang to use bash as preferred.
[Sat Jul 27 16:49:42 CST 2024] OK
[Sat Jul 27 16:49:42 CST 2024] Install success!
安装在主目录:~/.acme.sh/。重新通过终端(Terminal)连接到服务器,就可以使用 acme.sh 命令了。直接运行该命令,会看到详细的参数说明。
申请证书
acme.sh 实现了 acme 协议支持的所有验证协议,一般有两种方式验证:http 和 dns 验证。这里讲解 http 方式,它更简单一些。因为申请过程中,不需要修改域名解析记录。
使用 root 账号,执行以下命令
acme.sh --issue -d xxx.example-domain.com --nginx
出现以下关键提示信息,表示证书申请成功
[Sat Jul 27 17:12:11 CST 2024] Your cert is in: /root/.acme.sh/xxx.example-domain.com_ecc/xxx.example-domain.com.cer
[Sat Jul 27 17:12:11 CST 2024] Your cert key is in: /root/.acme.sh/xxx.example-domain.com_ecc/xxx.example-domain.com.key
[Sat Jul 27 17:12:11 CST 2024] The intermediate CA cert is in: /root/.acme.sh/xxx.example-domain.com_ecc/ca.cer
[Sat Jul 27 17:12:11 CST 2024] And the full chain certs is there: /root/.acme.sh/xxx.example-domain.com_ecc/fullchain.cer
证书所在目录:/root/.acme.sh/xxx.example-domain.com_ecc
申请过程中,acme.sh 程序会在你的 web 根目录创建文件:/.well-known/acme-challenge/oOJ0JzF1A7mfu9ZUTw74mdpnS9Ay1Rs7wWt61Bpnxm2。然后,证书颁发机构会通过网络访问该文件,如果能正常访问,说明该域名是你的。验证完成后,acme.sh 程序会删掉验证文件,不会留下痕迹。
安装证书
使用 root 账号,执行以下命令,将参数 --key-file 和 --fullchain-file 修改为你的证书文件将要放置的实际位置
acme.sh --install-cert -d xxx.example-domain.com \
--key-file /etc/nginx/cert/xxx.example-domain.key \
--fullchain-file /etc/nginx/cert/xxx.example-domain.fullchain.cer \
--reloadcmd "service nginx force-reload"
出现以下提示,说明安装成功
[Sat Jul 27 17:33:44 CST 2024] The domain 'xxx.example-domain.com' seems to have a ECC cert already, lets use ecc cert.
[Sat Jul 27 17:33:44 CST 2024] Installing key to: /etc/nginx/cert/xxx.example-domain.com.key
[Sat Jul 27 17:33:44 CST 2024] Installing full chain to: /etc/nginx/cert/xxx.example-domain.com.fullchain.cer
[Sat Jul 27 17:33:44 CST 2024] Run reload cmd: service nginx force-reload
Redirecting to /bin/systemctl force-reload nginx.service
[Sat Jul 27 17:33:44 CST 2024] Reload success
配置 https 服务
给 Nginx 增加一个新的站点配置文件,建议在上面的 Nginx 配置文件添加以下内容,因为它们都是为一个域名服务的,写在一个文件中便于管理
server {
listen 443 ssl;
server_name xxx.example-domain.com;
root /home/ericling/projects/my-test-project/web;
index index.html;
ssl_certificate /etc/nginx/cert/xxx.example-domain.fullchain.cer;
ssl_certificate_key /etc/nginx/cert/xxx.example-domain.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
# 这里省略其它配置,请自行补充
}
注意将上面的 ssl_certificate 和 ssl_certificate_key 参数的值,替换为安装证书时指定的路径。
测试 Nginx 配置文件,确保正确,并让它生效。
顺利的话,这时就可以通过 https 访问该域名了。
自动续期
这里申请的免费证书,默认的颁发机构是 ZeroSSL,有效期是 3 个月。之后每隔 2 个月,程序会自动执行续期操作(也就是重新申请新的证书),无需人工干预。我们可以看到,acme.sh 程序在 crontab 中添加了一条自动化任务:
1 10 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null
最后
参考资料:acme.sh 中文文档
这是《手把手教你》系列文章,希望通过浅显易懂的文字,教会你如何做一件事情。后续我会结合实际工作,持续更新本文。
想了解我,去看看我的项目和作品。