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

18 KiB
Raw Blame History

🚀 DesignerCEP Caddy 部署指南

为什么选择 Caddy

自动 HTTPS:无需手动申请证书,自动从 Let's Encrypt 获取并续期
配置简单:比 Nginx 简单 10 倍,一看就懂
开箱即用:自动处理 HTTP/2, GZIP 压缩
完美支持 Cloudflare:自动识别并配置


📦 1. 安装 Caddy

Ubuntu/Debian

# 安装依赖
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

# 添加 Caddy 官方仓库
dnf install 'dnf-command(copr)'
dnf copr enable @caddy/caddy
dnf install caddy

# 启动服务
sudo systemctl enable caddy
sudo systemctl start caddy

📁 2. 准备项目目录

# 创建项目目录
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 代理

# 创建 Caddyfile
sudo nano /etc/caddy/Caddyfile
# /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 橙云代理

sudo nano /etc/caddy/Caddyfile
# /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 配置

# 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 配置环境变量

# 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 管理服务

# 创建服务文件
sudo nano /etc/systemd/system/designer-cep.service
[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 安装依赖并启动

# 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 配置前端环境

# Designer/.env.production
VITE_API_SERVER=https://your-domain.com

6.2 构建前端

cd Designer
npm install
npm run build

6.3 上传到服务器

方法 A: 手动上传

# 在本地执行
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: 使用自动化脚本

# 在项目根目录执行
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

# 检查配置语法
sudo caddy validate --config /etc/caddy/Caddyfile

# 重启 Caddy
sudo systemctl restart caddy

# 查看状态
sudo systemctl status caddy

# 查看日志
sudo journalctl -u caddy -f

🧪 8. 测试部署

8.1 测试静态文件

# 测试 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

# 测试健康检查
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

# 模拟 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 没有解析到服务器

解决

# 检查 DNS 解析
nslookup your-domain.com

# 确保 A 记录指向服务器 IP
dig your-domain.com

Q2: API 请求 502 Bad Gateway

原因FastAPI 服务没有启动

解决

# 检查 FastAPI 状态
sudo systemctl status designer-cep

# 查看日志
sudo journalctl -u designer-cep -f

# 重启服务
sudo systemctl restart designer-cep

Q3: 静态文件 404

原因:文件路径不对

解决

# 检查文件是否存在
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

# 方法 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 模式(最简单)

# Caddyfile
{
    auto_https off
}

http://your-domain.com {
    # ... 配置
}

Cloudflare 设置:Flexible

Full (Strict) 模式(最安全)

  1. 生成 Cloudflare Origin Certificate
Cloudflare 控制台 → SSL/TLS → Origin Server → Create Certificate
  1. 下载证书并上传到服务器:
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/*
  1. 修改 Caddyfile
your-domain.com {
    tls /etc/caddy/certs/cloudflare-origin.pem /etc/caddy/certs/cloudflare-origin.key
    
    # ... 其他配置
}
  1. 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 日志

# 实时日志
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 日志

# 实时日志
sudo journalctl -u designer-cep -f

# 最近的错误
sudo journalctl -u designer-cep --since "1 hour ago" | grep -i error

性能监控

# 检查服务器资源
htop

# 检查端口监听
sudo netstat -tlnp | grep -E '(8000|80|443)'

# 检查 Caddy 进程
ps aux | grep caddy

🔄 12. 更新部署

更新前端

# 方法 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

更新后端

# 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 配置

# 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 一键部署!