Files
common-server-public/acme/README.md
张威33321 a9ec40a289 0908
2026-09-09 15:04:54 +08:00

99 lines
3.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 证书管理服务acme.sh
用宿主机上的 [acme.sh](https://github.com/acmesh-official/acme.sh) 管理 Let's Encrypt 证书:
纯 Shell 实现,不依赖 Python / snap / Docker 容器。
## 为什么换成 acme.sh
之前用 certbot 容器时有个绕不开的别扭点certbot 的 `--deploy-hook` 在**容器内**执行,
而我们要 reload 的 nginx 是**宿主机上的容器**,只能在容器里挂 `docker.sock`(等于把宿主机
root 交给容器),或者退而求其次每天无条件发一次 HUP。
acme.sh 直接跑在宿主机,`--reloadcmd` 天然在宿主机执行,**只在证书真正更新时才 reload**
顺带把 certbot 容器、Dockerfile、docker.sock、compose PATH 问题全部消掉。
## 架构
```
宿主机 容器
───────────────────────────────────── ──────────────────────────
acme.sh~/.acme.sh自带 cron
├─ 写挑战文件 ──▶ /var/www/certbot ──bind mount(ro)──▶ nginx-proxy
├─ 写证书 ──▶ /etc/letsencrypt ──bind mount(ro)──▶ nginx-proxy
└─ 续签后执行 reloadcmd: docker kill -s HUP nginx-proxy
用户 ─▶ frps(80/443) ─▶ frpc ─▶ nginx-proxy(80/8443)
```
## 目录约定
| 宿主机路径 | 用途 |
|---|---|
| `/var/www/certbot` | ACME HTTP-01 挑战文件 |
| `/etc/letsencrypt/live/<CERT_NAME>/` | 证书(默认 CERT_NAME=stonelan.cn |
| `nginx/ssl.d/` | HTTPS server 块,证书就绪后由 `enable-ssl.sh` 写入 |
5 个域名合成**一张 SAN 证书**放在同一个目录nginx 的 5 个 server 块都引用它。
## 使用方法
### 1. 安装
```bash
cd common-server-public/acme
chmod +x install.sh issue.sh renew.sh check-cert.sh
./install.sh
```
### 2. 申请证书(一键引导)
```bash
sudo ./issue.sh
```
依次完成:建目录 → 起 nginx此时无 HTTPS 配置)→ 申请证书 → 安装证书 →
写入 `ssl.d/` 并重载 nginx。
可用环境变量覆盖:
```bash
EMAIL=you@example.com \
CERT_NAME=stonelan.cn \
DOMAINS="fastgpt.stonelan.cn gitea.stonelan.cn image.stonelan.cn registry.stonelan.cn www.stonelan.cn" \
sudo -E ./issue.sh
```
### 3. 自动续签
`install.sh` 已让 acme.sh 自己写入 cron**无需额外配置**。
建议再加一条兜底告警(`crontab.example`
```cron
0 8 * * * bash <绝对路径>/check-cert.sh >> /var/log/acme-check.log 2>&1
```
## 故障排查
```bash
acme.sh --list # 已申请的证书
acme.sh --cron --debug 2 # 带调试跑一次续签
./check-cert.sh # 剩余天数
# 确认 nginx 只加载了 HTTP 配置(冷启动时属正常)
docker exec nginx-proxy nginx -T | grep -c "listen 8443"
# ACME 路径可达性
echo probe | sudo tee /var/www/certbot/.well-known/acme-challenge/test
curl -i http://fastgpt.stonelan.cn/.well-known/acme-challenge/test
```
## 注意事项
1. 需要 root或 sudo运行要写 `/etc/letsencrypt``/var/www`
2. nginx 容器 bind mount 的是**宿主机路径**,宿主机上这两个目录必须存在,
否则 docker 会自动创建成 root 所有的空目录
3. 挑战文件需要让容器内 nginx 可读,目录保持 755`issue.sh` 已处理)
4. CA 已显式固定为 Let's Encryptacme.sh 3.x 默认是 ZeroSSL
5. 证书有效期 90 天acme.sh 默认在剩余 30 天内续签