350 lines
7.1 KiB
Markdown
350 lines
7.1 KiB
Markdown
# APISIX SSL 证书自动管理
|
||
|
||
基于 Certbot + APISIX Admin API 的 SSL 证书自动申请和续期方案。
|
||
|
||
## 功能特性
|
||
|
||
- ✅ 自动申请 Let's Encrypt 免费 SSL 证书
|
||
- ✅ 自动将证书同步到 APISIX
|
||
- ✅ 自动续期证书(90 天有效期)
|
||
- ✅ 监听路由创建,自动为新域名申请证书
|
||
- ✅ 支持多域名证书
|
||
- ✅ 支持测试环境(staging)
|
||
|
||
## 目录结构
|
||
|
||
```
|
||
ssl_manager/
|
||
├── ssl_manager.py # SSL 证书管理主脚本
|
||
├── route_watcher.py # 路由监听服务
|
||
├── certbot_deploy_hook.sh # Certbot 部署钩子
|
||
├── config.json # 配置文件
|
||
├── requirements.txt # Python 依赖
|
||
└── README.md # 说明文档
|
||
```
|
||
|
||
## 安装步骤
|
||
|
||
### 1. 安装 Certbot
|
||
|
||
```bash
|
||
# Ubuntu/Debian
|
||
sudo apt-get update
|
||
sudo apt-get install certbot
|
||
|
||
# CentOS/RHEL
|
||
sudo yum install certbot
|
||
```
|
||
|
||
### 2. 安装 Python 依赖
|
||
|
||
```bash
|
||
cd /home/jingrow/apisix/ssl_manager
|
||
|
||
# 方法一:使用 uv(推荐,更快)
|
||
uv pip install --system -r requirements.txt
|
||
|
||
# 方法二:使用 pip3
|
||
pip3 install -r requirements.txt
|
||
```
|
||
|
||
### 3. 配置
|
||
|
||
配置已直接定义在 Python 文件中,**不需要** `config.json`。
|
||
|
||
**方式一:直接修改 Python 文件(推荐)**
|
||
|
||
编辑 `ssl_manager.py` 中的 `DEFAULT_CONFIG`:
|
||
|
||
```python
|
||
DEFAULT_CONFIG = {
|
||
'apisix_admin_url': 'http://localhost:9180',
|
||
'apisix_admin_key': '你的APISIX管理密钥', # 修改这里
|
||
'letsencrypt_email': 'your-email@example.com', # 修改这里
|
||
'letsencrypt_staging': False, # 生产环境改为 False
|
||
# ... 其他配置 ...
|
||
}
|
||
```
|
||
|
||
**方式二:使用环境变量**
|
||
|
||
```bash
|
||
export APISIX_ADMIN_KEY="your-admin-key"
|
||
export LETSENCRYPT_EMAIL="your-email@example.com"
|
||
export LETSENCRYPT_STAGING="false"
|
||
```
|
||
|
||
详细配置说明请查看 `CONFIG.md`
|
||
|
||
### 4. 创建 Webroot 目录
|
||
|
||
Certbot 需要 webroot 目录用于验证:
|
||
|
||
```bash
|
||
sudo mkdir -p /var/www/certbot
|
||
sudo chown -R www-data:www-data /var/www/certbot
|
||
```
|
||
|
||
### 5. 配置 APISIX 支持 Webroot 验证
|
||
|
||
需要在 APISIX 中配置一个路由,将 `/.well-known/acme-challenge/` 请求转发到 webroot 目录。
|
||
|
||
## 使用方法
|
||
|
||
### 手动申请证书
|
||
|
||
```bash
|
||
# 申请单个域名证书
|
||
python3 ssl_manager.py request --domain example.com
|
||
|
||
# 申请多域名证书
|
||
python3 ssl_manager.py request --domain example.com --additional-domains www.example.com api.example.com
|
||
```
|
||
|
||
### 手动续期证书
|
||
|
||
```bash
|
||
# 续期单个域名
|
||
python3 ssl_manager.py renew --domain example.com
|
||
|
||
# 续期所有证书
|
||
python3 ssl_manager.py renew-all
|
||
```
|
||
|
||
### 同步现有证书到 APISIX
|
||
|
||
```bash
|
||
python3 ssl_manager.py sync --domain example.com
|
||
```
|
||
|
||
### 检查证书过期时间
|
||
|
||
```bash
|
||
python3 ssl_manager.py check --domain example.com
|
||
```
|
||
|
||
### 启动路由监听服务
|
||
|
||
```bash
|
||
# 持续监听(每 60 秒检查一次)
|
||
python3 route_watcher.py
|
||
|
||
# 只执行一次
|
||
python3 route_watcher.py --once
|
||
|
||
# 自定义检查间隔
|
||
python3 route_watcher.py --interval 30
|
||
```
|
||
|
||
## 自动续期配置
|
||
|
||
### 方法一:使用 Certbot 自动续期 + 部署钩子
|
||
|
||
1. 配置 Certbot 自动续期:
|
||
|
||
```bash
|
||
# 编辑 Certbot 续期配置
|
||
sudo nano /etc/letsencrypt/renewal/example.com.conf
|
||
```
|
||
|
||
在配置文件中添加部署钩子:
|
||
|
||
```ini
|
||
[renewalparams]
|
||
deploy_hook = /home/jingrow/apisix/ssl_manager/certbot_deploy_hook.sh
|
||
```
|
||
|
||
2. 测试续期:
|
||
|
||
```bash
|
||
sudo certbot renew --dry-run
|
||
```
|
||
|
||
3. 设置 systemd timer(推荐):
|
||
|
||
创建 `/etc/systemd/system/certbot-renew.timer`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=Certbot Renewal Timer
|
||
|
||
[Timer]
|
||
OnCalendar=daily
|
||
RandomizedDelaySec=3600
|
||
Persistent=true
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
```
|
||
|
||
创建 `/etc/systemd/system/certbot-renew.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=Certbot Renewal Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/bin/certbot renew --quiet --deploy-hook /home/jingrow/apisix/ssl_manager/certbot_deploy_hook.sh
|
||
```
|
||
|
||
启用定时器:
|
||
|
||
```bash
|
||
sudo systemctl enable certbot-renew.timer
|
||
sudo systemctl start certbot-renew.timer
|
||
```
|
||
|
||
### 方法二:使用自定义脚本 + systemd timer
|
||
|
||
创建 `/etc/systemd/system/apisix-ssl-renew.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=APISIX SSL Certificate Renewal
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=oneshot
|
||
ExecStart=/usr/bin/python3 /home/jingrow/apisix/ssl_manager/ssl_manager.py renew-all
|
||
User=root
|
||
```
|
||
|
||
创建 `/etc/systemd/system/apisix-ssl-renew.timer`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=APISIX SSL Certificate Renewal Timer
|
||
|
||
[Timer]
|
||
OnCalendar=weekly
|
||
RandomizedDelaySec=3600
|
||
Persistent=true
|
||
|
||
[Install]
|
||
WantedBy=timers.target
|
||
```
|
||
|
||
启用:
|
||
|
||
```bash
|
||
sudo systemctl enable apisix-ssl-renew.timer
|
||
sudo systemctl start apisix-ssl-renew.timer
|
||
```
|
||
|
||
## 路由监听服务
|
||
|
||
路由监听服务会自动检测新创建的路由,并为其中的域名申请证书。
|
||
|
||
### 启动服务
|
||
|
||
```bash
|
||
# 使用 systemd(推荐)
|
||
sudo systemctl start apisix-route-watcher.service
|
||
|
||
# 或使用 screen/tmux
|
||
screen -S route-watcher
|
||
python3 route_watcher.py
|
||
```
|
||
|
||
### 创建 systemd 服务
|
||
|
||
创建 `/etc/systemd/system/apisix-route-watcher.service`:
|
||
|
||
```ini
|
||
[Unit]
|
||
Description=APISIX Route Watcher Service
|
||
After=network.target
|
||
|
||
[Service]
|
||
Type=simple
|
||
ExecStart=/usr/bin/python3 /home/jingrow/apisix/ssl_manager/route_watcher.py
|
||
Restart=always
|
||
RestartSec=10
|
||
User=root
|
||
|
||
[Install]
|
||
WantedBy=multi-user.target
|
||
```
|
||
|
||
启用服务:
|
||
|
||
```bash
|
||
sudo systemctl enable apisix-route-watcher.service
|
||
sudo systemctl start apisix-route-watcher.service
|
||
```
|
||
|
||
## 环境变量配置
|
||
|
||
也可以通过环境变量配置:
|
||
|
||
```bash
|
||
export APISIX_ADMIN_URL="http://localhost:9180"
|
||
export APISIX_ADMIN_KEY="your-admin-key"
|
||
export LETSENCRYPT_EMAIL="your-email@example.com"
|
||
export LETSENCRYPT_STAGING="false"
|
||
export WEBROOT_PATH="/var/www/certbot"
|
||
```
|
||
|
||
## 注意事项
|
||
|
||
1. **首次使用建议使用 staging 模式测试**:
|
||
```json
|
||
"letsencrypt_staging": true
|
||
```
|
||
|
||
2. **确保 80 端口可访问**:Let's Encrypt 需要验证域名所有权,通常使用 HTTP-01 验证方式。
|
||
|
||
3. **DNS 验证**:如果无法使用 HTTP-01 验证,可以配置 DNS-01 验证(需要修改脚本)。
|
||
|
||
4. **证书存储**:证书存储在 `/etc/letsencrypt/live/` 目录,请确保有备份。
|
||
|
||
5. **日志位置**:
|
||
- SSL 管理器日志:`/var/log/apisix-ssl-manager.log`
|
||
- 路由监听日志:`/var/log/apisix-route-watcher.log`
|
||
- Certbot 部署钩子日志:`/var/log/apisix-certbot-deploy.log`
|
||
|
||
## 故障排查
|
||
|
||
### 证书申请失败
|
||
|
||
1. 检查域名 DNS 解析是否正确
|
||
2. 检查 80 端口是否可访问
|
||
3. 检查 webroot 目录权限
|
||
4. 查看 Certbot 日志:`/var/log/letsencrypt/letsencrypt.log`
|
||
|
||
### 证书无法同步到 APISIX
|
||
|
||
1. 检查 APISIX Admin API 是否可访问
|
||
2. 检查 Admin Key 是否正确
|
||
3. 查看 SSL 管理器日志
|
||
|
||
### 自动续期不工作
|
||
|
||
1. 检查 systemd timer 状态:`systemctl status certbot-renew.timer`
|
||
2. 手动测试续期:`certbot renew --dry-run`
|
||
3. 检查部署钩子脚本权限:`chmod +x certbot_deploy_hook.sh`
|
||
|
||
## 测试
|
||
|
||
### 测试环境(staging)
|
||
|
||
```json
|
||
"letsencrypt_staging": true
|
||
```
|
||
|
||
Staging 环境有更高的申请频率限制,适合测试。
|
||
|
||
### 生产环境
|
||
|
||
测试通过后,设置:
|
||
|
||
```json
|
||
"letsencrypt_staging": false
|
||
```
|
||
|
||
## 许可证
|
||
|
||
Apache License 2.0
|