Initial commit - DesignerCEP Project with Caddy deployment

This commit is contained in:
zuowei1216
2025-12-19 21:27:17 +08:00
commit 8ea58fe480
170 changed files with 47469 additions and 0 deletions

View File

@@ -0,0 +1,820 @@
# 🚀 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` 一键部署!