From 7eecabaf3d7bd1f6690be902171c1ed7bd4d619c Mon Sep 17 00:00:00 2001 From: xiaoxia Date: Wed, 2 Sep 2026 15:25:27 +0800 Subject: [PATCH] =?UTF-8?q?feat(deploy):=20=E6=B7=BB=E5=8A=A0=E7=8E=AF?= =?UTF-8?q?=E5=A2=83=E9=85=8D=E7=BD=AE=E6=A8=A1=E6=9D=BF=20+=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=20compose=20=E8=B7=AF=E5=BE=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 deploy/configs/.env.staging — Staging 环境配置模板(含 MinIO) - 新增 deploy/configs/.env.production — Production 环境配置模板(无 MinIO) - 新增 deploy/configs/nginx-staging.conf — Staging Nginx 配置 - 新增 deploy/configs/nginx-production.conf — Production Nginx 配置 - 修复 infra/docker/compose.yml: GENERATED_FILES_HOST_DIR 去掉默认值, 改为 ?: 语法强制要求显式设置,防止 Production 静默指向 staging 目录 - 更新 .gitignore: 为 deploy/configs/ 下的模板文件添加例外 --- .gitignore | 3 + deploy/configs/.env.production | 227 +++++++++++++++++++++++++ deploy/configs/.env.staging | 244 +++++++++++++++++++++++++++ deploy/configs/nginx-production.conf | 51 ++++++ deploy/configs/nginx-staging.conf | 50 ++++++ infra/docker/compose.yml | 2 +- 6 files changed, 576 insertions(+), 1 deletion(-) create mode 100644 deploy/configs/.env.production create mode 100644 deploy/configs/.env.staging create mode 100644 deploy/configs/nginx-production.conf create mode 100644 deploy/configs/nginx-staging.conf diff --git a/.gitignore b/.gitignore index b97f016d6..96705506e 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,9 @@ ruff_cache/ .env.production .env.staging !.env.example +# 配置模板不受忽略规则限制 +!deploy/configs/.env.staging +!deploy/configs/.env.production # OS / editor .DS_Store diff --git a/deploy/configs/.env.production b/deploy/configs/.env.production new file mode 100644 index 000000000..14d480e64 --- /dev/null +++ b/deploy/configs/.env.production @@ -0,0 +1,227 @@ +# ============================================================ +# 小虾 SaaS — Production 环境配置模板 +# ============================================================ +# 使用方式:复制为 /var/lib/xiaoxia-saas-production/.env 并填入实际密钥 +# 敏感值标记为 ${PLACEHOLDER},部署前必须替换为真实值 +# ============================================================ + + +# ==================== 应用基本配置 ==================== + +# 应用名称 +APP_NAME=xiaoxia-saas + +# 环境标识 +APP_ENV=production + +# 关闭 Debug 模式 +DEBUG=false + +# 应用基础 URL(前端页面地址) +APP_BASE_URL=https://xiaoxiajianji.com + +# 对外公开的 API 基础 URL(用于生成回调链接等) +PUBLIC_API_BASE_URL=https://api.xiaoxiajianji.com + +# API 服务监听地址 +API_HOST=0.0.0.0 + +# API 服务监听端口 +API_PORT=8001 + +# 生产环境关闭自动建表,使用 alembic migration +AUTO_CREATE_SCHEMA=false + + +# ==================== 数据库配置 ==================== + +# 数据库连接串(格式:postgresql+psycopg://user:password@host:port/dbname) +# ${DATABASE_URL} — 替换为实际的 Production PostgreSQL 连接串 +DATABASE_URL=${DATABASE_URL} + +# 连接池大小(常驻连接数) +DATABASE_POOL_SIZE=20 + +# 连接池最大溢出连接数(pool_size + max_overflow = 最大并发连接数) +DATABASE_MAX_OVERFLOW=10 + +# 获取连接超时时间(秒) +DATABASE_POOL_TIMEOUT=30 + +# 连接回收时间(秒),防止数据库端主动断开导致的死连接 +DATABASE_POOL_RECYCLE=3600 + +# 不使用内存数据库 +USE_IN_MEMORY_DB=false + + +# ==================== Redis 配置 ==================== + +# Redis 连接 URL(格式:redis://[:password@]host:port/db) +# ${REDIS_URL} — 替换为实际的 Production Redis 连接串 +REDIS_URL=${REDIS_URL} + +# 启用 Redis Session 存储(多实例部署必须开启) +ENABLE_REDIS_SESSIONS=true + + +# ==================== Celery 任务队列 ==================== + +# Celery Broker(任务分发),使用 Redis db0 +CELERY_BROKER_URL=${CELERY_BROKER_URL} + +# Celery Result Backend(任务结果存储),使用 Redis db1 +CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND} + + +# ==================== Worker 配置 ==================== + +# Worker 进程名称 +WORKER_NAME=xiaoxia-saas-worker + +# Worker 并发数(同时执行的任务数) +WORKER_CONCURRENCY=4 + +# 每个子进程最多处理多少任务后重启(防止内存泄漏) +WORKER_MAX_TASKS_PER_CHILD=1000 + + +# ==================== JWT 认证配置 ==================== + +# JWT 签名密钥 — 必须设置为强随机字符串(至少32字符) +# ${JWT_SECRET_KEY} — 替换为实际的随机密钥 +JWT_SECRET_KEY=${JWT_SECRET_KEY} + +# JWT 签名算法 +JWT_ALGORITHM=HS256 + +# Access Token 过期时间(分钟) +JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30 + +# Refresh Token 过期时间(天) +JWT_REFRESH_TOKEN_EXPIRE_DAYS=30 + + +# ==================== 邮件配置 ==================== + +# 启用邮件投递 +ENABLE_EMAIL_DELIVERY=true + +# SMTP 服务器地址 +SMTP_HOST=smtp.gmail.com + +# SMTP 端口 +SMTP_PORT=587 + +# SMTP 用户名 +# ${SMTP_USER} — 替换为实际的 SMTP 用户名 +SMTP_USER=${SMTP_USER} + +# SMTP 密码 / 应用专用密码 +# ${SMTP_PASSWORD} — 替换为实际的 SMTP 密码 +SMTP_PASSWORD=${SMTP_PASSWORD} + +# 发件人邮箱 +SMTP_FROM_EMAIL=noreply@xiaoxia-saas.com + +# 发件人显示名称 +SMTP_FROM_NAME=小虾 SaaS + +# 启用 TLS +SMTP_USE_TLS=true + + +# ==================== 阿里云 OSS 配置 ==================== + +# OSS 区域 endpoint +OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com + +# OSS Access Key ID +# ${OSS_ACCESS_KEY_ID} — 替换为实际的 OSS Access Key ID +OSS_ACCESS_KEY_ID=${OSS_ACCESS_KEY_ID} + +# OSS Access Key Secret +# ${OSS_ACCESS_KEY_SECRET} — 替换为实际的 OSS Access Key Secret +OSS_ACCESS_KEY_SECRET=${OSS_ACCESS_KEY_SECRET} + +# OSS Bucket 名称 +OSS_BUCKET_NAME=xiaoxia-autocut + +# 直传最大文件大小(MB) +OSS_DIRECT_UPLOAD_MAX_MB=2000 + +# 直传签名有效期(秒) +OSS_DIRECT_UPLOAD_EXPIRE_SECONDS=900 + + +# ==================== CORS 配置 ==================== + +# 允许跨域的前端域名列表,逗号分隔 +CORS_ORIGINS_RAW=https://xiaoxiajianji.com,https://www.xiaoxiajianji.com + + +# ==================== 生成文件路径 ==================== + +# 容器内生成文件目录(固定值,勿改) +GENERATED_FILES_DIR=/app/generated + +# 生成文件 URL 前缀 +GENERATED_FILES_URL_PREFIX=/generated-files + +# 主机上生成文件目录(供 Docker volume bind mount 使用) +GENERATED_FILES_HOST_DIR=/var/lib/xiaoxia-saas-production/generated + + +# ==================== 渲染引擎配置 ==================== + +# 渲染引擎选择:legacy(旧引擎,稳定)/ unified(新架构) +RENDER_ENGINE=legacy + + +# ==================== CosyVoice 语音合成 ==================== + +# 阿里云百灵语音合成服务 API Key +# ${COSYVOICE_API_KEY} — 替换为实际的 CosyVoice API Key +COSYVOICE_API_KEY=${COSYVOICE_API_KEY} + +# API 基础 URL +COSYVOICE_BASE_URL=https://dashscope.aliyuncs.com/api/v1 + +# 模型选择:cosyvoice-v3-flash(推荐)/ cosyvoice-v3-plus +COSYVOICE_MODEL=cosyvoice-v3-flash + +# 音色:v3 系列系统音色带 _v3 后缀 +COSYVOICE_VOICE=longxiaochun_v3 + +# 采样率 +COSYVOICE_SAMPLE_RATE=22050 + +# 输出格式 +COSYVOICE_FORMAT=mp3 + +# 音色克隆模型名(固定值) +COSYVOICE_CLONE_MODEL=voice-enrollment + + +# ==================== 豆包大模型(火山引擎方舟)==================== + +# 豆包 API Key +# ${DOUBAO_API_KEY} — 替换为实际的豆包 API Key +DOUBAO_API_KEY=${DOUBAO_API_KEY} + +# 模型名称 +DOUBAO_MODEL=doubao-seed-1-6-250615 + +# API 基础 URL +DOUBAO_BASE_URL=https://ark.cn-beijing.volces.com/api/v3 + +# 请求超时时间(秒) +DOUBAO_TIMEOUT=30 + +# 最大重试次数 +DOUBAO_MAX_RETRIES=2 + + +# ==================== 监控(可选)==================== +# Sentry DSN(取消注释并填入实际值以启用错误追踪) +# SENTRY_DSN=${SENTRY_DSN} diff --git a/deploy/configs/.env.staging b/deploy/configs/.env.staging new file mode 100644 index 000000000..423c7acb8 --- /dev/null +++ b/deploy/configs/.env.staging @@ -0,0 +1,244 @@ +# ============================================================ +# 小虾 SaaS — Staging 环境配置模板 +# ============================================================ +# 使用方式:复制为 /var/lib/xiaoxia-saas-staging/.env 并填入实际密钥 +# 敏感值标记为 ${PLACEHOLDER},部署前必须替换为真实值 +# ============================================================ + + +# ==================== 应用基本配置 ==================== + +# 应用名称 +APP_NAME=xiaoxia-saas + +# 环境标识 +APP_ENV=staging + +# 关闭 Debug 模式 +DEBUG=false + +# 应用基础 URL(前端页面地址) +APP_BASE_URL=https://staging.xiaoxiajianji.com + +# 对外公开的 API 基础 URL(用于生成回调链接等) +PUBLIC_API_BASE_URL=https://staging-api.xiaoxiajianji.com + +# API 服务监听地址 +API_HOST=0.0.0.0 + +# API 服务监听端口 +API_PORT=8000 + +# 生产/预发布环境关闭自动建表,使用 alembic migration +AUTO_CREATE_SCHEMA=false + + +# ==================== 数据库配置 ==================== + +# 数据库连接串(格式:postgresql+psycopg://user:password@host:port/dbname) +# ${DATABASE_URL} — 替换为实际的 Staging PostgreSQL 连接串 +DATABASE_URL=${DATABASE_URL} + +# 连接池大小(常驻连接数) +DATABASE_POOL_SIZE=20 + +# 连接池最大溢出连接数(pool_size + max_overflow = 最大并发连接数) +DATABASE_MAX_OVERFLOW=10 + +# 获取连接超时时间(秒) +DATABASE_POOL_TIMEOUT=30 + +# 连接回收时间(秒),防止数据库端主动断开导致的死连接 +DATABASE_POOL_RECYCLE=3600 + +# 不使用内存数据库 +USE_IN_MEMORY_DB=false + + +# ==================== Redis 配置 ==================== + +# Redis 连接 URL(格式:redis://[:password@]host:port/db) +# ${REDIS_URL} — 替换为实际的 Staging Redis 连接串 +REDIS_URL=${REDIS_URL} + +# 启用 Redis Session 存储(多实例部署必须开启) +ENABLE_REDIS_SESSIONS=true + + +# ==================== Celery 任务队列 ==================== + +# Celery Broker(任务分发),使用 Redis db0 +CELERY_BROKER_URL=${CELERY_BROKER_URL} + +# Celery Result Backend(任务结果存储),使用 Redis db1 +CELERY_RESULT_BACKEND=${CELERY_RESULT_BACKEND} + + +# ==================== Worker 配置 ==================== + +# Worker 进程名称 +WORKER_NAME=xiaoxia-saas-worker + +# Worker 并发数(同时执行的任务数) +WORKER_CONCURRENCY=1 + +# 每个子进程最多处理多少任务后重启(防止内存泄漏) +WORKER_MAX_TASKS_PER_CHILD=1000 + + +# ==================== JWT 认证配置 ==================== + +# JWT 签名密钥 — 必须设置为强随机字符串(至少32字符) +# ${JWT_SECRET_KEY} — 替换为实际的随机密钥 +JWT_SECRET_KEY=${JWT_SECRET_KEY} + +# JWT 签名算法 +JWT_ALGORITHM=HS256 + +# Access Token 过期时间(分钟) +JWT_ACCESS_TOKEN_EXPIRE_MINUTES=30 + +# Refresh Token 过期时间(天) +JWT_REFRESH_TOKEN_EXPIRE_DAYS=30 + + +# ==================== 邮件配置 ==================== + +# 启用邮件投递 +ENABLE_EMAIL_DELIVERY=true + +# SMTP 服务器地址 +SMTP_HOST=smtp.gmail.com + +# SMTP 端口 +SMTP_PORT=587 + +# SMTP 用户名 +# ${SMTP_USER} — 替换为实际的 SMTP 用户名 +SMTP_USER=${SMTP_USER} + +# SMTP 密码 / 应用专用密码 +# ${SMTP_PASSWORD} — 替换为实际的 SMTP 密码 +SMTP_PASSWORD=${SMTP_PASSWORD} + +# 发件人邮箱 +SMTP_FROM_EMAIL=noreply@xiaoxia-saas.com + +# 发件人显示名称 +SMTP_FROM_NAME=小虾 SaaS + +# 启用 TLS +SMTP_USE_TLS=true + + +# ==================== 阿里云 OSS 配置 ==================== + +# OSS 区域 endpoint +OSS_ENDPOINT=oss-cn-hangzhou.aliyuncs.com + +# OSS Access Key ID +# ${OSS_ACCESS_KEY_ID} — 替换为实际的 OSS Access Key ID +OSS_ACCESS_KEY_ID=${OSS_ACCESS_KEY_ID} + +# OSS Access Key Secret +# ${OSS_ACCESS_KEY_SECRET} — 替换为实际的 OSS Access Key Secret +OSS_ACCESS_KEY_SECRET=${OSS_ACCESS_KEY_SECRET} + +# OSS Bucket 名称 +OSS_BUCKET_NAME=xiaoxia-autocut + +# 直传最大文件大小(MB) +OSS_DIRECT_UPLOAD_MAX_MB=2000 + +# 直传签名有效期(秒) +OSS_DIRECT_UPLOAD_EXPIRE_SECONDS=900 + + +# ==================== MinIO 配置(Staging 独有)==================== +# Staging 环境使用 MinIO 替代 OSS 进行文件存储测试 + +# MinIO 服务 Endpoint +# ${MINIO_ENDPOINT} — 替换为实际的 MinIO 地址 +MINIO_ENDPOINT=${MINIO_ENDPOINT} + +# MinIO Access Key +# ${MINIO_ACCESS_KEY} — 替换为实际的 MinIO Access Key +MINIO_ACCESS_KEY=${MINIO_ACCESS_KEY} + +# MinIO Secret Key +# ${MINIO_SECRET_KEY} — 替换为实际的 MinIO Secret Key +MINIO_SECRET_KEY=${MINIO_SECRET_KEY} + +# MinIO Bucket 名称 +MINIO_BUCKET=${MINIO_BUCKET} + +# 是否使用 SSL 连接 MinIO +MINIO_USE_SSL=false + + +# ==================== CORS 配置 ==================== + +# 允许跨域的前端域名列表,逗号分隔 +CORS_ORIGINS_RAW=https://staging.xiaoxiajianji.com,https://staging-web.xiaoxiajianji.com + + +# ==================== 生成文件路径 ==================== + +# 容器内生成文件目录(固定值,勿改) +GENERATED_FILES_DIR=/app/generated + +# 生成文件 URL 前缀 +GENERATED_FILES_URL_PREFIX=/generated-files + +# 主机上生成文件目录(供 Docker volume bind mount 使用) +GENERATED_FILES_HOST_DIR=/var/lib/xiaoxia-saas-staging/generated + + +# ==================== 渲染引擎配置 ==================== + +# 渲染引擎选择:legacy(旧引擎,稳定)/ unified(新架构) +RENDER_ENGINE=legacy + + +# ==================== CosyVoice 语音合成 ==================== + +# 阿里云百灵语音合成服务 API Key +# ${COSYVOICE_API_KEY} — 替换为实际的 CosyVoice API Key +COSYVOICE_API_KEY=${COSYVOICE_API_KEY} + +# API 基础 URL +COSYVOICE_BASE_URL=https://dashscope.aliyuncs.com/api/v1 + +# 模型选择:cosyvoice-v3-flash(推荐)/ cosyvoice-v3-plus +COSYVOICE_MODEL=cosyvoice-v3-flash + +# 音色:v3 系列系统音色带 _v3 后缀 +COSYVOICE_VOICE=longxiaochun_v3 + +# 采样率 +COSYVOICE_SAMPLE_RATE=22050 + +# 输出格式 +COSYVOICE_FORMAT=mp3 + +# 音色克隆模型名(固定值) +COSYVOICE_CLONE_MODEL=voice-enrollment + + +# ==================== 豆包大模型(火山引擎方舟)==================== + +# 豆包 API Key +# ${DOUBAO_API_KEY} — 替换为实际的豆包 API Key +DOUBAO_API_KEY=${DOUBAO_API_KEY} + +# 模型名称 +DOUBAO_MODEL=doubao-seed-1-6-250615 + +# API 基础 URL +DOUBAO_BASE_URL=https://ark.cn-beijing.volces.com/api/v3 + +# 请求超时时间(秒) +DOUBAO_TIMEOUT=30 + +# 最大重试次数 +DOUBAO_MAX_RETRIES=2 diff --git a/deploy/configs/nginx-production.conf b/deploy/configs/nginx-production.conf new file mode 100644 index 000000000..70b4b1a02 --- /dev/null +++ b/deploy/configs/nginx-production.conf @@ -0,0 +1,51 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml+rss; + + client_max_body_size 800m; + + # SPA routing - index.html 禁止缓存,确保每次获取最新版本 + location / { + try_files $uri /index.html; + } + + # API proxy — Production 环境代理到 production API 容器 + resolver 127.0.0.11 valid=10s; + resolver_timeout 5s; + location /api/ { + proxy_pass http://xiaoxia-api-production:8000/api/; + 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_read_timeout 300s; + proxy_send_timeout 300s; + proxy_request_buffering off; + } + + # Generated files — 通过 alias 映射容器内 /app/generated/ 目录 + location /generated-files/ { + alias /app/generated/; + } + + # Assets with legacy fallback — 部署期间兼容旧版缓存的 hash 文件名 + # 先在当前镜像中找,找不到去 legacy-assets 目录找(从旧版本容器中备份的) + location ^~ /assets/ { + expires 1y; + add_header Cache-Control "public, immutable"; + try_files $uri /assets-legacy$uri =404; + } + + # 静态资源长缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} diff --git a/deploy/configs/nginx-staging.conf b/deploy/configs/nginx-staging.conf new file mode 100644 index 000000000..cc6cc4ab9 --- /dev/null +++ b/deploy/configs/nginx-staging.conf @@ -0,0 +1,50 @@ +server { + listen 80; + server_name _; + root /usr/share/nginx/html; + index index.html; + + gzip on; + gzip_vary on; + gzip_min_length 1024; + gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml+rss; + + client_max_body_size 800m; + + # SPA routing - index.html 禁止缓存,确保每次获取最新版本 + location = /index.html { + add_header Cache-Control "no-cache, no-store, must-revalidate"; + add_header Pragma "no-cache"; + expires 0; + } + + # SPA fallback + location / { + try_files $uri /index.html; + } + + # API proxy — Staging 环境代理到 staging API 容器 + resolver 127.0.0.11 valid=10s; + resolver_timeout 5s; + location /api/ { + proxy_pass http://xiaoxia-api-staging:8000/api/; + 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_read_timeout 300s; + proxy_send_timeout 300s; + proxy_request_buffering off; + } + + # Generated files — 通过 alias 映射容器内 /app/generated/ 目录 + location /generated-files/ { + alias /app/generated/; + } + + # 静态资源长缓存 + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + expires 1y; + add_header Cache-Control "public, immutable"; + } +} diff --git a/infra/docker/compose.yml b/infra/docker/compose.yml index 5c7164c7e..614789d6e 100755 --- a/infra/docker/compose.yml +++ b/infra/docker/compose.yml @@ -208,7 +208,7 @@ volumes: # 重要: 确保主机目录存在且有正确权限 # Staging: /var/lib/xiaoxia-saas-staging/generated # Production: /var/lib/xiaoxia-saas-production/generated - device: ${GENERATED_FILES_HOST_DIR:-/var/lib/xiaoxia-saas-staging/generated} + device: ${GENERATED_FILES_HOST_DIR:?GENERATED_FILES_HOST_DIR must be set in .env} # =========================================== # 网络配置 -- 2.54.0