270 lines
7.0 KiB
Markdown
270 lines
7.0 KiB
Markdown
# CLAUDE.md — nginx-proxy-ai
|
||
|
||
tlyq.ai 反向代理服务,管理所有子站点的 SSL 终止、路由转发和性能优化。
|
||
|
||
## 项目概述
|
||
|
||
nginx-proxy-ai 是 tlyq.ai 域名的统一入口,负责:
|
||
- SSL/TLS 终止(所有 HTTPS 流量)
|
||
- 反向代理到后端 Docker 容器
|
||
- Gzip 压缩
|
||
- 静态资源缓存
|
||
- HTTP → HTTPS 强制跳转
|
||
|
||
## SSL 证书配置(必遵)
|
||
|
||
### 证书来源
|
||
|
||
| 证书路径 | 类型 | 用途 |
|
||
|---------|------|------|
|
||
| `/etc/letsencrypt/live/www.tlyq.ai/` | Let's Encrypt | **所有站点共用** |
|
||
| `/etc/letsencrypt/live/www.tlyq.ai-0001/` | Let's Encrypt | SSO 站点专用 |
|
||
|
||
### ⚠️ 禁止事项
|
||
|
||
1. **禁止使用 CloudFlare Origin 证书**:这是自签名证书,浏览器不信任
|
||
2. **禁止手动放置证书文件**:必须通过 certbot 申请
|
||
3. **禁止修改 `/etc/letsencrypt/` 目录权限**
|
||
|
||
### 新增站点证书流程
|
||
|
||
1. 申请证书:
|
||
```bash
|
||
ssh txjp "certbot certonly --webroot -w /var/www/html -d new-site.tlyq.ai"
|
||
```
|
||
|
||
2. 配置 nginx 引用现有证书(推荐共用 `www.tlyq.ai`):
|
||
```nginx
|
||
ssl_certificate /etc/letsencrypt/live/www.tlyq.ai/fullchain.pem;
|
||
ssl_certificate_key /etc/letsencrypt/live/www.tlyq.ai/privkey.pem;
|
||
```
|
||
|
||
3. 重载配置:
|
||
```bash
|
||
ssh txjp "docker exec nginx-ai nginx -s reload"
|
||
```
|
||
|
||
### 证书续期机制
|
||
|
||
证书续期通过 **systemd timer** 自动管理,无需人工干预。
|
||
|
||
#### 工作原理
|
||
|
||
```
|
||
systemd timer (snap.certbot.renew.timer)
|
||
↓ 每天 01:30 和 22:32 触发
|
||
systemd service (snap.certbot.renew.service)
|
||
↓ 执行
|
||
certbot renew --timer="00:00~24:00/2"
|
||
↓ 续期成功后
|
||
deploy hook → docker exec nginx-ai nginx -s reload
|
||
```
|
||
|
||
#### 关键文件
|
||
|
||
| 组件 | 路径 | 说明 |
|
||
|------|------|------|
|
||
| Timer | `/etc/systemd/system/snap.certbot.renew.timer` | 定时触发器 |
|
||
| Service | `/etc/systemd/system/snap.certbot.renew.service` | 执行续期的服务 |
|
||
| Hook | `/etc/letsencrypt/renewal-hooks/deploy/reload-nginx.sh` | 续期后重载 nginx |
|
||
|
||
#### Timer 配置
|
||
|
||
```ini
|
||
[Timer]
|
||
OnCalendar=*-*-* 01:30 # 每天 01:30
|
||
OnCalendar=*-*-* 22:32 # 每天 22:32
|
||
```
|
||
|
||
每天检查两次,距离到期 < 30 天时自动续期。
|
||
|
||
#### 常用管理命令
|
||
|
||
```bash
|
||
# 查看定时器状态
|
||
ssh txjp "systemctl status snap.certbot.renew.timer"
|
||
|
||
# 查看下次运行时间
|
||
ssh txjp "systemctl list-timers snap.certbot.renew.timer"
|
||
|
||
# 手动触发续期
|
||
ssh txjp "systemctl start snap.certbot.renew.service"
|
||
|
||
# 查看续期日志
|
||
ssh txjp "journalctl -u snap.certbot.renew.service --since '1 hour ago'"
|
||
|
||
# 检查证书有效期
|
||
ssh txjp "openssl x509 -in /etc/letsencrypt/live/www.tlyq.ai/fullchain.pem -noout -dates"
|
||
|
||
# 测试续期(不实际续期)
|
||
ssh txjp "certbot renew --dry-run"
|
||
```
|
||
|
||
## 文件结构
|
||
|
||
```
|
||
nginx-proxy-ai/
|
||
├── nginx.conf # 主配置(全局优化参数)
|
||
├── nginx-local.conf # 本地测试配置
|
||
├── docker-compose.yml # 生产 Docker 配置
|
||
├── docker-compose.local.yml # 本地测试 Docker 配置
|
||
├── conf.d/ # 站点反向代理配置
|
||
│ ├── www-ai.conf # www.tlyq.ai
|
||
│ ├── cloud-ai.conf # cloud.tlyq.ai(纯静态)
|
||
│ ├── token-ai.conf # token.tlyq.ai(纯静态)
|
||
│ ├── issue-ai.conf # issue.tlyq.ai
|
||
│ ├── assets-ai.conf # assets.tlyq.ai
|
||
│ ├── git-ai.conf # git.tlyq.ai(Gitea)
|
||
│ ├── oa-ai.conf # oa.tlyq.ai
|
||
│ ├── sso-ai.conf # sso.tlyq.ai(Authelia)
|
||
│ ├── monitor-ai.conf # monitor.tlyq.ai
|
||
│ ├── root-domain.conf # tlyq.ai → www.tlyq.ai 跳转
|
||
│ └── letsencrypt.conf # ACME HTTP-01 验证
|
||
├── certs/ # 本地测试自签名证书(不纳入生产)
|
||
└── static/ # 静态文件目录
|
||
```
|
||
|
||
## 部署流程
|
||
|
||
### 生产部署(txjp 服务器)
|
||
|
||
```bash
|
||
# 1. 上传配置(排除本地测试文件)
|
||
rsync -avz --exclude='node_modules' --exclude='.git' \
|
||
--exclude='nginx-local.conf' --exclude='docker-compose.local.yml' \
|
||
--exclude='certs/' \
|
||
./ txjp:/root/docker/nginx-proxy-ai/
|
||
|
||
# 2. 验证配置
|
||
ssh txjp "docker exec nginx-ai nginx -t"
|
||
|
||
# 3. 平滑重载
|
||
ssh txjp "docker exec nginx-ai nginx -s reload"
|
||
```
|
||
|
||
### 本地测试
|
||
|
||
```bash
|
||
docker compose -f docker-compose.local.yml up -d
|
||
```
|
||
|
||
## 性能优化参数
|
||
|
||
### 全局优化(nginx.conf http 块)
|
||
|
||
```nginx
|
||
# IO 优化
|
||
sendfile on;
|
||
tcp_nopush on;
|
||
tcp_nodelay on;
|
||
|
||
# Keepalive
|
||
keepalive_timeout 65;
|
||
keepalive_requests 1000;
|
||
|
||
# 客户端超时
|
||
client_max_body_size 16m;
|
||
client_body_buffer_size 128k;
|
||
client_header_timeout 30s;
|
||
send_timeout 30s;
|
||
|
||
# Gzip
|
||
gzip on;
|
||
gzip_min_length 1k;
|
||
gzip_comp_level 5;
|
||
gzip_types text/plain text/css application/json application/javascript application/xml image/svg+xml;
|
||
```
|
||
|
||
### SSL 安全配置
|
||
|
||
```nginx
|
||
ssl_protocols TLSv1.2 TLSv1.3;
|
||
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
|
||
ssl_prefer_server_ciphers on;
|
||
ssl_session_cache shared:SSL:10m;
|
||
ssl_session_timeout 1d;
|
||
ssl_session_tickets on;
|
||
server_tokens off;
|
||
```
|
||
|
||
### 反代默认参数
|
||
|
||
```nginx
|
||
proxy_http_version 1.1;
|
||
proxy_set_header Host $host;
|
||
proxy_set_header X-Real-IP $remote_addr;
|
||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||
proxy_set_header X-Forwarded-Proto $scheme;
|
||
proxy_set_header Connection "";
|
||
proxy_connect_timeout 3s;
|
||
proxy_send_timeout 30s;
|
||
proxy_read_timeout 30s;
|
||
proxy_buffer_size 16k;
|
||
proxy_buffers 8 16k;
|
||
proxy_busy_buffers_size 32k;
|
||
```
|
||
|
||
## 常用排查命令
|
||
|
||
```bash
|
||
# 配置语法检查
|
||
docker exec nginx-ai nginx -t
|
||
|
||
# 查看完整合并配置
|
||
docker exec nginx-ai nginx -T
|
||
|
||
# 查看 SSL 配置
|
||
docker exec nginx-ai nginx -T | grep -E 'ssl_protocols|ssl_ciphers|ssl_certificate'
|
||
|
||
# 测试 SSL 连接
|
||
echo | openssl s_client -connect 127.0.0.1:443 -servername www.tlyq.ai 2>/dev/null | grep -E 'Protocol|Cipher'
|
||
|
||
# 检查证书有效期
|
||
ssh txjp "openssl x509 -in /etc/letsencrypt/live/www.tlyq.ai/fullchain.pem -noout -dates"
|
||
```
|
||
|
||
## 故障排查
|
||
|
||
### SSL 不安全提示
|
||
|
||
1. 检查证书是否为 Let's Encrypt:
|
||
```bash
|
||
ssh txjp "openssl x509 -in /etc/letsencrypt/live/www.tlyq.ai/fullchain.pem -noout -issuer"
|
||
```
|
||
应显示 `Let's Encrypt`,而非 `CloudFlare`
|
||
|
||
2. 检查 SSL 协议和加密套件:
|
||
```bash
|
||
docker exec nginx-ai nginx -T | grep -E 'ssl_protocols|ssl_ciphers'
|
||
```
|
||
必须配置 `ssl_protocols TLSv1.2 TLSv1.3`
|
||
|
||
### 502 Bad Gateway
|
||
|
||
1. 检查后端容器是否运行:
|
||
```bash
|
||
docker ps | grep -E 'www-ai|assets-ai|issue-ai'
|
||
```
|
||
|
||
2. 检查容器网络连通性:
|
||
```bash
|
||
docker exec nginx-ai ping assets-ai
|
||
```
|
||
|
||
### 配置不生效
|
||
|
||
1. 确认配置语法正确:
|
||
```bash
|
||
docker exec nginx-ai nginx -t
|
||
```
|
||
|
||
2. 确认已重载:
|
||
```bash
|
||
docker exec nginx-ai nginx -s reload
|
||
```
|
||
|
||
3. 确认容器挂载路径正确:
|
||
```bash
|
||
docker inspect nginx-ai | grep -A5 Mounts
|
||
```
|