---
name: tencent-ssl-nginx-management
description: Manage SSL certificates with Tencent Cloud DNS and update nginx configurations — wildcard cert申请、MySQL 端口保护、批量更新 nginx 配置
version: 1.0.0
created: 2026-04-14
tags: [ssl, nginx, tencent-cloud, certbot, security, docker]
---

# Tencent SSL + Nginx Management Skill

用于申请腾讯云 DNS 验证的通配符 SSL 证书，并批量更新 nginx 配置。同时包含 Docker 服务安全加固（MySQL 端口保护）。

## 适用场景

- 申请 `*.domain.com` 通配符证书
- 使用腾讯云 DNSPod 进行 DNS-01 验证
- 批量更新多个 nginx 虚拟主机配置
- Docker 容器 MySQL 端口安全加固

## 前置条件

```bash
# 1. 安装 certbot 和腾讯云 DNS 插件
pip3 install certbot certbot-dns-tencentcloud

# 2. 准备腾讯云 API 密钥
# 获取地址：https://console.cloud.tencent.com/cam/capi
# 需要 DNSPod DNS 解析权限
export TENCENTCLOUD_SECRET_ID="AKIDxxx"
export TENCENTCLOUD_SECRET_KEY="xxx"
```

## 步骤 1: 申请通配符证书

```bash
# 设置环境变量（临时，不保存）
# ⚠️ 替换为您的真实密钥，不要保存此文件！
export TENCENTCLOUD_SECRET_ID="AKIDxxx"
export TENCENTCLOUD_SECRET_KEY="xxx"

# 申请通配符证书（DNS-01 验证）
certbot certonly \
  --authenticator dns-tencentcloud \
  -d "*.liupeizhi.top" -d "liupeizhi.top" \
  --email admin@liupeizhi.top \
  --agree-tos \
  --non-interactive

# 验证证书
certbot certificates
```

**注意**: 必须使用 `--authenticator dns-tencentcloud`，不能用 `--dns-tencentcloud`（会报 ambiguous option 错误）

## 步骤 2: 批量更新 nginx 配置

```bash
# 查看所有 SSL 配置文件
grep -l "ssl_certificate" /etc/nginx/conf.d/*.conf

# 批量替换证书路径（从旧证书到新证书）
sed -i 's|/etc/letsencrypt/live/old-domain.top/|/etc/letsencrypt/live/new-domain.top/|g' \
  /etc/nginx/conf.d/*.conf

# 验证 nginx 配置
nginx -t

# 重载 nginx
nginx -s reload
```

## 步骤 3: MySQL 端口保护 + Nginx 后端端口调整

### MySQL 端口保护（可选）

如果 MySQL 容器端口暴露到公网，建议改为仅内部访问：

```bash
# 编辑 docker-compose.yml
# 将 ports 改为 expose：
# ports:
#   - "3306:3306"
# 改为：
# expose:
#   - "3306"

# 重启 MySQL 容器
cd /path/to/docker-compose
docker compose up -d mysql

# 验证端口不再暴露
docker port container_name
# 应该返回空（无公网映射）

# 访问方式改为：
docker exec -it container_name mysql -uroot -p
```

### Nginx 后端端口调整（可选）

如需修改 nginx 反向代理的后端端口：

```bash
# 编辑指定站点配置
# 将 proxy_pass 从旧端口改为新端口
sed -i 's|proxy_pass http://127.0.0.1:旧端口;|proxy_pass http://127.0.0.1:新端口;|g' \
  /etc/nginx/conf.d/站点名.conf

# 示例：将 liupeizhi.top 从 8080 改为 6003
sed -i 's|proxy_pass http://127.0.0.1:8080;|proxy_pass http://127.0.0.1:6003;|g' \
  /etc/nginx/conf.d/liupeizhi.top.conf

# 验证并重载
nginx -t && nginx -s reload
```

**验证**:
```bash
# 检查配置是否生效
grep "proxy_pass" /etc/nginx/conf.d/站点名.conf

# 测试 HTTP 重定向
curl -s -o /dev/null -w "%{http_code}" http://域名
# 应返回 301（重定向到 HTTPS）
```

## 步骤 4: 配置自动续期

```bash
# 测试续期（dry-run）
certbot renew --dry-run

# 查看续期日志
tail -f /var/log/letsencrypt/letsencrypt.log

# 设置续期提醒（cron）
# 证书过期前 30 天自动续期，Certbot 默认已配置
```

## 常见问题

### Q: certbot 报 "ambiguous option" 错误
**A**: 使用 `--authenticator dns-tencentcloud` 而不是 `--dns-tencentcloud`

### Q: 系统文件无法用 patch 工具修改
**A**: 使用 `terminal` 工具 + `sed` 命令，需要用户批准

### Q: 证书申请失败 "记录编号错误"
**A**: 这是 DNS 传播延迟的正常警告，证书通常已成功申请

### Q: nginx 重载后配置不生效
**A**: 检查 `nginx -t` 输出，确认无语法错误；检查证书路径是否正确

## 文件结构

```
/etc/letsencrypt/
├── live/
│   ├── domain.com/          # 新申请的通配符证书
│   │   ├── fullchain.pem    # 完整证书链
│   │   ├── privkey.pem      # 私钥
│   │   ├── cert.pem         # 证书
│   │   └── chain.pem        # 中间证书
│   └── old-domain.com/      # 旧证书（可清理）
├── archive/                  # 证书归档
└── renewal/                  # 续期配置

/etc/nginx/conf.d/
├── site1.conf               # 虚拟主机配置
├── site2.conf
└── ...
```

## 安全建议

1. **MySQL 端口**: 永远不要暴露到公网，使用 `expose` + Docker 网络
2. **API 密钥**: 临时设置环境变量，不要保存到配置文件
3. **证书权限**: `chmod 644` 证书文件，`chmod 600` 私钥文件
4. **定期续期**: 设置监控告警，证书过期前 30 天提醒

## 清理旧证书（可选）

```bash
# 删除旧证书
certbot delete --cert-name old-domain.com

# 清理 nginx 中不再使用的配置
# 手动检查 /etc/nginx/conf.d/ 中的废弃文件
```

## 验证清单

- [ ] 证书申请成功（`certbot certificates` 显示 89 天有效期）
- [ ] nginx 配置测试通过（`nginx -t`）
- [ ] nginx 重载成功（`nginx -s reload`）
- [ ] 所有站点 HTTPS 正常访问
- [ ] MySQL 端口不再暴露（`docker port` 返回空）
- [ ] 自动续期测试通过（`certbot renew --dry-run`）
- [ ] 后端端口配置正确（`grep proxy_pass` 验证）
