用acme.sh给fastapi服务整个证书

背景

自己搞了个小网站,采用的fastapi+htmx技术,之前一直在阿里云上申请免费证书,以前的有效期是一年,现在变成了3个月,而且在阿里云上申请,还要等几十分钟到几个小时不等,比较麻烦。于是寻找替代方案。

原方案

  1. 定时到阿里云上申请免费证书,等待下发;
  2. 下载证书,scp到服务器上,替换旧证书;
  3. 重启nginx(用nginx是因为同一台机器上有多个应用);

新方案

采用acme.sh
读完官方文档,我选择了http直接申请证书再安装到本地的方式。
所有命令都采用的root账户。

step 1: 安装acme.sh

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

step 2:申请证书

1
acme.sh --issue -d example.com --webroot /var/www/html/

在执行这个命令之前,请确保/var/www/html/存在,我用的nginx,所以在nginx的配置中,对应的example.com的80口配置块中,增加了如下配置:

1
2
3
4
5
# 用于解决acme.sh安装证书时报错404错误
location ^~ /.well-known/acme-challenge/ {
root /var/www/html/;
default_type "text/plain";
}

证书申请过程中,会自动在该目录去创建一个随机文件,用于验证服务器的归属,验证链接形如:http://example.com/.well-known/acme-challenge/xxxxxxxxxxxxxxxxxx,有可能会报错。
403:就是权限问题,查一下/var/www/html/目录的拥用者、命令的执行用户,以及nginx的运行用户是不是一个;
404:检查nginx配置中/var/www/html/的网站目录是否设置正确;

step 3:安装证书

1
2
3
4
acme.sh --install-cert -d example.com \
--key-file /home/worker/ssl/example.com.key \
--fullchain-file /home/worker/ssl/example.com.pem \
--reloadcmd "systemctl restart nginx"

step 4:定期执行

acme.sh安装之后,默认会创建一个crontab任务:

1
48 6 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null

意思是每天6点48分执行,我的输出是这样的:

1
2
3
4
5
6
7
[Fri Jan 24 02:09:54 PM CST 2025] ===Starting cron===
[Fri Jan 24 02:09:54 PM CST 2025] Renewing: 'example.com'
[Fri Jan 24 02:09:54 PM CST 2025] Renewing using Le_API=https://acme-v02.api.letsencrypt.org/directory
[Fri Jan 24 02:09:54 PM CST 2025] Skipping. Next renewal time is: 2025-03-24T03:24:46Z
[Fri Jan 24 02:09:54 PM CST 2025] Add '--force' to force renewal.
[Fri Jan 24 02:09:54 PM CST 2025] Skipped example.com_ecc
[Fri Jan 24 02:09:54 PM CST 2025] ===End cron===

感觉每天会检查一次证书过期时间,再申请证书,然后发邮件给我,但安装估计还得手动,先不慌全自动,让它跑着,看看是不是这样。

其他

  1. 我没有选用nginx模式,因为没跑通,老说我的配置有问题,但是nginx -t是对的。
  2. DNS模式没有尝试过,有时间再试吧。

用acme.sh给fastapi服务整个证书
https://www.kisstools.com/2025/01/24/experiences/用acme给fastapi服务整个证书/
作者
kisstools
发布于
2025年1月24日
许可协议