Files
DP/tempdocs/Caddy部署指南.md

821 lines
18 KiB
Markdown
Raw 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.
# 🚀 DesignerCEP Caddy 部署指南
## 为什么选择 Caddy
**自动 HTTPS**:无需手动申请证书,自动从 Let's Encrypt 获取并续期
**配置简单**:比 Nginx 简单 10 倍,一看就懂
**开箱即用**:自动处理 HTTP/2, GZIP 压缩
**完美支持 Cloudflare**:自动识别并配置
---
## 📦 1. 安装 Caddy
### Ubuntu/Debian
```bash
# 安装依赖
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
# 添加 Caddy 官方仓库
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
# 更新并安装
sudo apt update
sudo apt install caddy
# 验证安装
caddy version
```
### CentOS/RHEL
```bash
# 添加 Caddy 官方仓库
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy
# 启动服务
sudo systemctl enable caddy
sudo systemctl start caddy
```
---
## 📁 2. 准备项目目录
```bash
# 创建项目目录
sudo mkdir -p /var/www/DesignerCEP/Server/static/{shell,core,downloads}
# 设置权限
sudo chown -R $USER:$USER /var/www/DesignerCEP
chmod -R 755 /var/www/DesignerCEP
```
---
## ⚙️ 3. 配置 Caddy
### 方案 A: 标准部署Let's Encrypt 自动证书)
**适用于**:独立域名,不使用 Cloudflare 代理
```bash
# 创建 Caddyfile
sudo nano /etc/caddy/Caddyfile
```
```caddy
# /etc/caddy/Caddyfile
# ========== 主站配置 ==========
your-domain.com, www.your-domain.com {
# ✅ Caddy 会自动处理 HTTPS 证书
# ========== API 请求 → FastAPI ==========
handle /api/* {
reverse_proxy localhost:8000 {
# 传递真实 IP
header_up X-Real-IP {remote_host}
header_up X-Forwarded-For {remote_host}
header_up X-Forwarded-Proto {scheme}
}
}
# ========== Shell 在线登录页 ==========
handle /shell/* {
root * /var/www/DesignerCEP/Server/static/shell
try_files {path} {path}/ /shell/index.html
file_server
# HTML 不缓存
@html {
path *.html
}
header @html Cache-Control "no-cache, no-store, must-revalidate"
# JS/CSS 长期缓存
@assets {
path *.js *.css
}
header @assets Cache-Control "public, max-age=31536000, immutable"
}
# ========== Core 核心应用 ==========
handle /core/* {
root * /var/www/DesignerCEP/Server/static/core
file_server
# HTML 不缓存
@html {
path *.html
}
header @html Cache-Control "no-cache, no-store, must-revalidate"
# JS/CSS 长期缓存
@assets {
path *.js *.css
}
header @assets Cache-Control "public, max-age=31536000, immutable"
}
# ========== 下载文件 ==========
handle /downloads/* {
root * /var/www/DesignerCEP/Server/static/downloads
file_server
# 启用断点续传
header Accept-Ranges bytes
# 缓存 1 天
header Cache-Control "public, max-age=86400"
}
# ========== 根路径重定向 ==========
handle / {
redir /shell/ permanent
}
# ========== 通用配置 ==========
# 自动 GZIP 压缩
encode gzip zstd
# 安全头
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
-Server # 隐藏服务器信息
}
# 日志
log {
output file /var/log/caddy/designer-cep.log {
roll_size 100mb
roll_keep 10
}
}
}
```
### 方案 B: Cloudflare 代理部署(推荐)
**适用于**:域名使用 Cloudflare 橙云代理
```bash
sudo nano /etc/caddy/Caddyfile
```
```caddy
# /etc/caddy/Caddyfile (Cloudflare 版本)
{
# ✅ 关闭自动 HTTPSCloudflare 已经提供)
auto_https off
# 或者使用内部证书
# auto_https disable_redirects
}
# ========== HTTP 配置Cloudflare 会加 HTTPS==========
http://your-domain.com, http://www.your-domain.com {
# ========== API 请求 → FastAPI ==========
handle /api/* {
reverse_proxy localhost:8000 {
# ✅ 从 Cloudflare 获取真实 IP
header_up X-Real-IP {header.CF-Connecting-IP}
header_up X-Forwarded-For {header.CF-Connecting-IP}
header_up X-Forwarded-Proto https
}
}
# ========== Shell 在线登录页 ==========
handle /shell/* {
root * /var/www/DesignerCEP/Server/static/shell
try_files {path} {path}/ /shell/index.html
file_server
@html path *.html
header @html Cache-Control "no-cache, no-store, must-revalidate"
@assets path *.js *.css
header @assets Cache-Control "public, max-age=31536000, immutable"
}
# ========== Core 核心应用 ==========
handle /core/* {
root * /var/www/DesignerCEP/Server/static/core
file_server
@html path *.html
header @html Cache-Control "no-cache, no-store, must-revalidate"
@assets path *.js *.css
header @assets Cache-Control "public, max-age=31536000, immutable"
}
# ========== 下载文件 ==========
handle /downloads/* {
root * /var/www/DesignerCEP/Server/static/downloads
file_server
header Accept-Ranges bytes
header Cache-Control "public, max-age=86400"
}
# ========== 根路径重定向 ==========
handle / {
redir /shell/ permanent
}
# ========== 通用配置 ==========
encode gzip zstd
header {
X-Frame-Options "SAMEORIGIN"
X-Content-Type-Options "nosniff"
X-XSS-Protection "1; mode=block"
-Server
}
log {
output file /var/log/caddy/designer-cep.log {
roll_size 100mb
roll_keep 10
}
}
}
```
---
## 🔧 4. 修改后端代码(支持 CEP 环境)
### 4.1 修改 FastAPI 的 CORS 配置
```python
# Server/app/main.py
from fastapi import FastAPI, Request
from fastapi.middleware.cors import CORSMiddleware
import os
app = FastAPI(title=settings.PROJECT_NAME)
# 环境判断
IS_DEV = os.getenv("ENV", "development") == "development"
# ========== CORS 配置 ==========
if IS_DEV:
# 开发环境:宽松配置
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
else:
# 生产环境:严格配置
allowed_origins = os.getenv("ALLOWED_ORIGINS", "").split(",")
app.add_middleware(
CORSMiddleware,
allow_origins=allowed_origins,
allow_credentials=True,
allow_methods=["GET", "POST", "PUT", "DELETE", "OPTIONS"],
allow_headers=["*"],
)
# ✅ 特殊处理 CEP 环境Origin: null
@app.middleware("http")
async def cep_cors_middleware(request: Request, call_next):
origin = request.headers.get("origin")
# CEP 环境的 Origin 是 null 或 cep://
if origin in ["null", None] or (origin and origin.startswith("cep://")):
response = await call_next(request)
response.headers["Access-Control-Allow-Origin"] = "*"
response.headers["Access-Control-Allow-Credentials"] = "true"
response.headers["Access-Control-Allow-Methods"] = "GET, POST, PUT, DELETE, OPTIONS"
response.headers["Access-Control-Allow-Headers"] = "*"
return response
return await call_next(request)
# ========== API 路由(保持不变)==========
app.include_router(auth.router, prefix=f"{settings.API_V1_STR}/auth", tags=["authentication"])
app.include_router(client.router, prefix=f"{settings.API_V1_STR}/client", tags=["client"])
app.include_router(admin.router, prefix=f"{settings.API_V1_STR}/admin", tags=["admin"])
app.include_router(analytics.router, prefix=f"{settings.API_V1_STR}/analytics", tags=["analytics"])
app.include_router(jsx_demo.router, prefix=f"{settings.API_V1_STR}/jsx_demo", tags=["jsx_demo"])
# ❌ 删除静态文件挂载(交给 Caddy 处理)
# app.mount("/download", ...) # 删除
# app.mount("/shell", ...) # 删除
# app.mount("/core", ...) # 删除
@app.get("/")
def read_root():
return {"message": "DesignerCEP API Server", "version": "1.0.0"}
@app.get("/health")
def health_check():
return {"status": "healthy"}
@app.on_event("startup")
def on_startup():
init_db()
```
### 4.2 配置环境变量
```bash
# Server/.env
ENV=production
PROJECT_NAME=DesignerCEP
API_V1_STR=/api/v1
SECRET_KEY=your-secret-key-here
DATABASE_URL=mysql://user:password@localhost:3306/designer_cep
# 生产环境允许的来源
ALLOWED_ORIGINS=https://your-domain.com,https://www.your-domain.com
# 是否由 FastAPI 提供静态文件(生产环境设为 false
SERVE_STATIC=false
```
---
## 🚀 5. 部署 FastAPI 服务
### 5.1 使用 Systemd 管理服务
```bash
# 创建服务文件
sudo nano /etc/systemd/system/designer-cep.service
```
```ini
[Unit]
Description=DesignerCEP FastAPI Application
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/var/www/DesignerCEP/Server
Environment="PATH=/var/www/DesignerCEP/Server/venv/bin"
ExecStart=/var/www/DesignerCEP/Server/venv/bin/gunicorn app.main:app -w 4 -k uvicorn.workers.UvicornWorker -b 127.0.0.1:8000
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
### 5.2 安装依赖并启动
```bash
# 1. 创建虚拟环境
cd /var/www/DesignerCEP/Server
python3 -m venv venv
source venv/bin/activate
# 2. 安装依赖
pip install -r requirements.txt
pip install gunicorn uvicorn[standard]
# 3. 测试运行
uvicorn app.main:app --host 127.0.0.1 --port 8000
# 4. 启动服务
sudo systemctl daemon-reload
sudo systemctl enable designer-cep
sudo systemctl start designer-cep
# 5. 检查状态
sudo systemctl status designer-cep
```
---
## 📤 6. 部署前端文件
### 6.1 配置前端环境
```bash
# Designer/.env.production
VITE_API_SERVER=https://your-domain.com
```
### 6.2 构建前端
```bash
cd Designer
npm install
npm run build
```
### 6.3 上传到服务器
#### 方法 A: 手动上传
```bash
# 在本地执行
cd Designer/dist
# 上传 Shell
scp -r Shell/* user@your-server:/var/www/DesignerCEP/Server/static/shell/
# 上传 Core
scp -r Designer/* user@your-server:/var/www/DesignerCEP/Server/static/core/1.0.6/
# 打包并上传 Shell.zip
zip -r shell-1.0.6.zip Shell/
scp shell-1.0.6.zip user@your-server:/var/www/DesignerCEP/Server/static/downloads/
```
#### 方法 B: 使用自动化脚本
```bash
# 在项目根目录执行
cd AdminTool
# 首次配置
python auto_deploy_core.py --version 1.0.6 --setup
# 输入配置信息:
# - 服务器地址: your-domain.com
# - SSH 端口: 22
# - 用户名: root
# - 密码: ******
# - 远程路径: /var/www/DesignerCEP/Server/static
# 部署
python auto_deploy_core.py --version 1.0.6 --deploy --update-db
```
---
## ✅ 7. 启动 Caddy
```bash
# 检查配置语法
sudo caddy validate --config /etc/caddy/Caddyfile
# 重启 Caddy
sudo systemctl restart caddy
# 查看状态
sudo systemctl status caddy
# 查看日志
sudo journalctl -u caddy -f
```
---
## 🧪 8. 测试部署
### 8.1 测试静态文件
```bash
# 测试 Shell
curl -I https://your-domain.com/shell/
# 期望输出:
# HTTP/2 200
# content-type: text/html
# 测试 Core
curl -I https://your-domain.com/core/1.0.6/
# 测试下载
curl -I https://your-domain.com/downloads/shell-1.0.6.zip
```
### 8.2 测试 API
```bash
# 测试健康检查
curl https://your-domain.com/api/v1/health
# 期望输出:
# {"status":"healthy"}
# 测试登录接口
curl -X POST https://your-domain.com/api/v1/client/login \
-H "Content-Type: application/json" \
-d '{"username":"test","password":"test","device_id":"test-device"}'
```
### 8.3 测试 CEP CORS
```bash
# 模拟 CEP 环境的预检请求
curl -X OPTIONS https://your-domain.com/api/v1/client/login \
-H "Origin: null" \
-H "Access-Control-Request-Method: POST" \
-v
# 期望输出:
# Access-Control-Allow-Origin: *
# Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
```
### 8.4 浏览器测试
1. 打开 `https://your-domain.com/shell/`
2. 输入用户名密码登录
3. 按 F12 打开开发者工具
4. 查看 Network 标签:
- ✅ 所有请求都是 HTTPS
- ✅ API 请求有 `Authorization: Bearer xxx`
- ✅ 没有 CORS 错误
---
## 🔍 9. 常见问题
### Q1: Caddy 自动证书失败
**原因**:域名 DNS 没有解析到服务器
**解决**
```bash
# 检查 DNS 解析
nslookup your-domain.com
# 确保 A 记录指向服务器 IP
dig your-domain.com
```
### Q2: API 请求 502 Bad Gateway
**原因**FastAPI 服务没有启动
**解决**
```bash
# 检查 FastAPI 状态
sudo systemctl status designer-cep
# 查看日志
sudo journalctl -u designer-cep -f
# 重启服务
sudo systemctl restart designer-cep
```
### Q3: 静态文件 404
**原因**:文件路径不对
**解决**
```bash
# 检查文件是否存在
ls -la /var/www/DesignerCEP/Server/static/shell/
ls -la /var/www/DesignerCEP/Server/static/core/1.0.6/
# 检查权限
sudo chown -R www-data:www-data /var/www/DesignerCEP
sudo chmod -R 755 /var/www/DesignerCEP
```
### Q4: Cloudflare 无限重定向
**原因**Cloudflare SSL 模式设置错误
**解决**
1. 进入 Cloudflare 控制台
2. SSL/TLS → Overview
3. 选择 **"Flexible"** 模式(因为 Caddy 配置的是 HTTP
或者修改 Caddyfile 使用 HTTPS
```caddy
# 方法 1: 自签名证书
your-domain.com {
tls internal
# ... 其他配置
}
# 方法 2: Cloudflare Origin Certificate
your-domain.com {
tls /etc/caddy/certs/cloudflare-origin.pem /etc/caddy/certs/cloudflare-origin.key
# ... 其他配置
}
```
---
## 🎯 10. Cloudflare 最佳实践
### 10.1 SSL/TLS 配置
```
Cloudflare 控制台 → SSL/TLS → Overview
选择模式:
- ❌ Off - 不使用 HTTPS
- ✅ Flexible - Cloudflare ←HTTPS→ 用户Cloudflare ←HTTP→ 源站(推荐简单部署)
- ⚠️ Full - 双向 HTTPS但不验证源站证书
- ✅ Full (Strict) - 双向 HTTPS验证证书推荐生产环境
```
**推荐方案**
#### Flexible 模式(最简单)
```caddy
# Caddyfile
{
auto_https off
}
http://your-domain.com {
# ... 配置
}
```
Cloudflare 设置:`Flexible`
#### Full (Strict) 模式(最安全)
1. 生成 Cloudflare Origin Certificate
```
Cloudflare 控制台 → SSL/TLS → Origin Server → Create Certificate
```
2. 下载证书并上传到服务器:
```bash
sudo mkdir -p /etc/caddy/certs
sudo nano /etc/caddy/certs/cloudflare-origin.pem # 粘贴证书
sudo nano /etc/caddy/certs/cloudflare-origin.key # 粘贴私钥
sudo chmod 600 /etc/caddy/certs/*
```
3. 修改 Caddyfile
```caddy
your-domain.com {
tls /etc/caddy/certs/cloudflare-origin.pem /etc/caddy/certs/cloudflare-origin.key
# ... 其他配置
}
```
4. Cloudflare 设置:`Full (Strict)`
### 10.2 性能优化
```
Cloudflare 控制台设置:
1. Speed → Optimization
- ✅ Auto Minify: HTML, CSS, JS
- ✅ Brotli 压缩
2. Caching → Configuration
- ✅ Caching Level: Standard
- ✅ Browser Cache TTL: Respect Existing Headers
3. Network
- ✅ HTTP/2
- ✅ HTTP/3 (QUIC)
```
---
## 📊 11. 监控和日志
### 查看 Caddy 日志
```bash
# 实时日志
sudo journalctl -u caddy -f
# 访问日志
sudo tail -f /var/log/caddy/designer-cep.log
# 错误日志
sudo journalctl -u caddy --since "1 hour ago" | grep -i error
```
### 查看 FastAPI 日志
```bash
# 实时日志
sudo journalctl -u designer-cep -f
# 最近的错误
sudo journalctl -u designer-cep --since "1 hour ago" | grep -i error
```
### 性能监控
```bash
# 检查服务器资源
htop
# 检查端口监听
sudo netstat -tlnp | grep -E '(8000|80|443)'
# 检查 Caddy 进程
ps aux | grep caddy
```
---
## 🔄 12. 更新部署
### 更新前端
```bash
# 方法 A: 手动
cd Designer
npm run build
scp -r dist/Shell/* user@server:/var/www/DesignerCEP/Server/static/shell/
scp -r dist/Designer/* user@server:/var/www/DesignerCEP/Server/static/core/1.0.7/
# 方法 B: 自动化
cd AdminTool
python auto_deploy_core.py --version 1.0.7 --deploy --update-db
```
### 更新后端
```bash
# 1. SSH 到服务器
ssh user@your-server
# 2. 拉取最新代码
cd /var/www/DesignerCEP/Server
git pull
# 3. 更新依赖
source venv/bin/activate
pip install -r requirements.txt
# 4. 重启服务
sudo systemctl restart designer-cep
# 5. 检查状态
sudo systemctl status designer-cep
```
### 更新 Caddy 配置
```bash
# 1. 修改配置
sudo nano /etc/caddy/Caddyfile
# 2. 验证配置
sudo caddy validate --config /etc/caddy/Caddyfile
# 3. 重新加载(不中断服务)
sudo systemctl reload caddy
```
---
## 🎉 完成!
访问地址:
- **Shell 登录页**`https://your-domain.com/shell/`
- **Core 应用**`https://your-domain.com/core/1.0.6/`
- **API 文档**`https://your-domain.com/api/v1/docs`
---
## 📋 部署检查清单
- [ ] Caddy 已安装并启动
- [ ] Caddyfile 配置正确
- [ ] FastAPI 服务运行正常
- [ ] 前端文件已上传
- [ ] 环境变量配置正确
- [ ] CORS 支持 CEP 环境
- [ ] MySQL 数据库已更新
- [ ] HTTPS 证书正常
- [ ] 静态文件缓存正确
- [ ] API 请求正常
- [ ] CEP 扩展测试通过
- [ ] 浏览器访问正常
---
**Caddy 的优势总结**
- ✅ 配置只有 Nginx 的 1/3 长度
- ✅ 自动 HTTPS无需 Certbot
- ✅ 自动续期证书
- ✅ 内置 GZIP/Brotli 压缩
- ✅ 配置更直观易懂
- ✅ 错误提示更友好
**下一步**:运行 `python auto_deploy_core.py --version 1.0.6 --deploy --update-db` 一键部署!