feat: production branch with deploy config for baota panel
- Add deploy/ directory with production env, supervisor, nginx, migration configs - Include all latest features: admin management, feedback, footer with ICP/beian - Database: foreign_trade (PostgreSQL), user: foreign_trade - Frontend: trade.yuzhiran.com, backend proxy via Nginx
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# 生产部署文档(宝塔面板)
|
||||
|
||||
## 前提条件
|
||||
|
||||
宝塔面板已安装:
|
||||
- Nginx
|
||||
- PostgreSQL(已有数据库 `foreign_trade`)
|
||||
- Redis
|
||||
- Python 3.11+
|
||||
|
||||
## 目录结构(宝塔站点根目录)
|
||||
|
||||
```
|
||||
/www/wwwroot/trade.yuzhiran.com/
|
||||
├── backend/ # FastAPI 后端代码
|
||||
│ ├── .env # 生产环境变量
|
||||
│ ├── app/
|
||||
│ ├── alembic/
|
||||
│ └── ...
|
||||
├── frontend/ # 前端静态文件
|
||||
│ └── dist/ # uni-app 构建产物
|
||||
└── deploy/ # 部署配置(此目录)
|
||||
```
|
||||
|
||||
## 部署步骤
|
||||
|
||||
### 1. 上传代码到服务器
|
||||
|
||||
将项目代码(production 分支)上传到 `/www/wwwroot/trade.yuzhiran.com/`
|
||||
|
||||
### 2. 配置后端环境变量
|
||||
|
||||
```bash
|
||||
cp deploy/backend/.env.production backend/.env
|
||||
# 编辑 backend/.env,填入:
|
||||
# - SECRET_KEY(随机字符串,用于 JWT 签名)
|
||||
# - AI API Key(OPENAI_API_KEY 或 SENSENOVA_API_KEY 等)
|
||||
vim backend/.env
|
||||
```
|
||||
|
||||
### 3. 安装后端依赖 & 运行迁移
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
alembic upgrade head
|
||||
```
|
||||
|
||||
### 4. 构建前端
|
||||
|
||||
```bash
|
||||
cd uni-app
|
||||
npm install
|
||||
npm run build:h5
|
||||
# 产物在 dist/build/h5/ 目录
|
||||
# 将 dist/build/h5/ 下的内容复制到 /www/wwwroot/trade.yuzhiran.com/frontend/dist/
|
||||
```
|
||||
|
||||
### 5. 配置 Nginx(宝塔面板操作)
|
||||
|
||||
在宝塔面板中:
|
||||
1. 添加站点 `trade.yuzhiran.com`
|
||||
2. 站点根目录设为 `/www/wwwroot/trade.yuzhiran.com/frontend/dist`
|
||||
3. 修改 Nginx 配置,参考 `deploy/frontend/nginx.conf`
|
||||
|
||||
关键配置点:
|
||||
- 根目录指向前端 dist
|
||||
- `/api/` 反向代理到 `http://127.0.0.1:8000`
|
||||
- SPA fallback: `try_files $uri $uri/ /index.html`
|
||||
|
||||
### 6. 启动后端(宝塔 Python 项目管理器)
|
||||
|
||||
在宝塔面板中使用 **Python项目管理器**:
|
||||
- 项目路径:`/www/wwwroot/trade.yuzhiran.com/backend`
|
||||
- Python 版本:3.11
|
||||
- 启动命令:`uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2`
|
||||
- 项目名称:`trademate-backend`
|
||||
|
||||
或者使用 Supervisor 命令行部署:
|
||||
```bash
|
||||
pip install supervisor
|
||||
supervisord -c deploy/backend/supervisord.conf
|
||||
```
|
||||
|
||||
### 7. 验证
|
||||
|
||||
- 访问 https://trade.yuzhiran.com → 前端正常加载
|
||||
- 访问 https://trade.yuzhiran.com/api/health → 返回 `{"status": "ok"}`
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Q: 数据库迁移失败?**
|
||||
A: 确认 PostgreSQL 中 `foreign_trade` 数据库已创建,用户有权限。
|
||||
```sql
|
||||
CREATE DATABASE foreign_trade;
|
||||
GRANT ALL PRIVILEGES ON DATABASE foreign_trade TO foreign_trade;
|
||||
```
|
||||
|
||||
**Q: 前端 API 请求 502?**
|
||||
A: 检查后端是否启动,以及 Nginx 中 `/api/` 的 proxy_pass 地址是否正确。
|
||||
|
||||
**Q: CORS 报错?**
|
||||
A: 确认 `backend/.env` 中的 `FRONTEND_URL` 与实际前端域名一致。
|
||||
@@ -0,0 +1,59 @@
|
||||
# 生产环境配置(基于宝塔面板 PostgreSQL foreign_trade 数据库)
|
||||
APP_NAME=TradeMate
|
||||
SECRET_KEY=change-this-to-a-random-secret-key
|
||||
JWT_ALGORITHM=HS256
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=60
|
||||
REFRESH_TOKEN_EXPIRE_DAYS=30
|
||||
|
||||
# 数据库(foreign_trade)
|
||||
DATABASE_URL=postgresql+asyncpg://foreign_trade:dWFNi67nHNbPbjmP@localhost:5432/foreign_trade
|
||||
|
||||
# Redis(宝塔自带,默认端口)
|
||||
REDIS_URL=redis://localhost:6379/0
|
||||
|
||||
# Celery
|
||||
CELERY_BROKER_URL=redis://localhost:6379/1
|
||||
CELERY_RESULT_BACKEND=redis://localhost:6379/2
|
||||
|
||||
# AI 提供商(按需填入)
|
||||
OPENAI_API_KEY=
|
||||
ANTHROPIC_API_KEY=
|
||||
DEEPL_API_KEY=
|
||||
|
||||
SENSENOVA_API_KEY=
|
||||
SENSENOVA_BASE_URL=https://token.sensenova.cn/v1
|
||||
SENSENOVA_MODEL=sensenova-6.7-flash-lite
|
||||
|
||||
IFLYTEK_API_KEY=
|
||||
IFLYTEK_API_BASE=https://maas-api.cn-huabei-1.xf-yun.com/v2
|
||||
IFLYTEK_MODEL=astron-code-latest
|
||||
|
||||
LOCAL_MODEL_ENABLED=false
|
||||
LOCAL_MODEL_URL=http://localhost:8001
|
||||
|
||||
# WhatsApp Cloud API
|
||||
WHATSAPP_API_TOKEN=
|
||||
WHATSAPP_PHONE_NUMBER_ID=
|
||||
WHATSAPP_WEBHOOK_VERIFY_TOKEN=
|
||||
|
||||
# 微信
|
||||
WECHAT_APP_ID=
|
||||
WECHAT_APP_SECRET=
|
||||
|
||||
# 汇率 API
|
||||
EXCHANGE_RATE_API_KEY=
|
||||
|
||||
# 文件存储
|
||||
UPLOAD_DIR=./uploads
|
||||
MAX_UPLOAD_SIZE=10485760
|
||||
|
||||
# 错误监控 (Sentry)
|
||||
SENTRY_DSN=
|
||||
DEBUG=false
|
||||
|
||||
# URL(以宝塔实际域名/端口为准)
|
||||
FRONTEND_URL=https://trade.yuzhiran.com
|
||||
BACKEND_URL=https://api.trade.yuzhiran.com
|
||||
|
||||
# 数据库调试关闭
|
||||
DB_ECHO=false
|
||||
@@ -0,0 +1,13 @@
|
||||
[program:trademate-backend]
|
||||
command=/www/server/panel/pyenv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2 --proxy-headers --forwarded-allow-ips='*'
|
||||
directory=/www/wwwroot/trade.yuzhiran.com/backend
|
||||
user=www
|
||||
autostart=true
|
||||
autorestart=true
|
||||
stopasgroup=true
|
||||
killasgroup=true
|
||||
stdout_logfile=/www/wwwlogs/trademate-backend.log
|
||||
stderr_logfile=/www/wwwlogs/trademate-backend.error.log
|
||||
stdout_logfile_maxbytes=50MB
|
||||
stderr_logfile_maxbytes=50MB
|
||||
environment=PATH="/www/server/panel/pyenv/bin:/usr/local/bin:/usr/bin:/bin",HOME="/home/www"
|
||||
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
# 生产数据库迁移脚本
|
||||
# 使用方式: bash deploy/database/migrate.sh
|
||||
# 注意:需先在 backend/ 目录下配置好 .env 或设置好环境变量
|
||||
|
||||
set -e
|
||||
|
||||
cd "$(dirname "$0")/../../backend"
|
||||
|
||||
# 检查 .env 是否存在
|
||||
if [ ! -f ".env" ]; then
|
||||
echo "❌ 未找到 .env 文件,请先复制 deploy/backend/.env.production 到 backend/.env"
|
||||
echo " cp deploy/backend/.env.production backend/.env"
|
||||
echo " 然后编辑 .env 填入 SECRET_KEY 和 AI API Key"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "🔧 激活虚拟环境..."
|
||||
if [ -d "venv" ]; then
|
||||
source venv/bin/activate
|
||||
fi
|
||||
|
||||
echo "📦 安装/更新依赖..."
|
||||
pip install -r requirements.txt -q
|
||||
|
||||
echo "🗄️ 运行数据库迁移..."
|
||||
alembic upgrade head
|
||||
|
||||
echo "✅ 迁移完成"
|
||||
@@ -0,0 +1,70 @@
|
||||
# 宝塔面板 Nginx 配置
|
||||
# 注意:请勿直接覆盖宝塔生成的配置文件!
|
||||
# 将此配置中的 server 块复制到宝塔对应站点的配置中
|
||||
# 宝塔路径: /www/server/panel/vhost/nginx/trade.yuzhiran.com.conf
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
server_name trade.yuzhiran.com;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
server_name trade.yuzhiran.com;
|
||||
|
||||
# SSL 证书(宝塔面板中配置,或取消注释以下行)
|
||||
# ssl_certificate /www/server/panel/vhost/cert/trade.yuzhiran.com/fullchain.pem;
|
||||
# ssl_certificate_key /www/server/panel/vhost/cert/trade.yuzhiran.com/privkey.pem;
|
||||
# ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
|
||||
# ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
|
||||
# ssl_prefer_server_ciphers on;
|
||||
|
||||
# 前端静态文件(uni-app build:h5 产物)
|
||||
root /www/wwwroot/trade.yuzhiran.com/frontend/dist;
|
||||
index index.html;
|
||||
|
||||
# gzip
|
||||
gzip on;
|
||||
gzip_min_length 1k;
|
||||
gzip_comp_level 6;
|
||||
gzip_types text/plain text/css text/javascript application/json application/javascript image/svg+xml;
|
||||
|
||||
# API 反向代理到后端
|
||||
location /api/ {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
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 120s;
|
||||
proxy_send_timeout 120s;
|
||||
|
||||
# WebSocket 支持(如有需要)
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection "upgrade";
|
||||
}
|
||||
|
||||
# 上传文件(如有需要可配置单独的路径)
|
||||
# location /uploads/ {
|
||||
# alias /www/wwwroot/trade.yuzhiran.com/backend/uploads/;
|
||||
# expires 7d;
|
||||
# }
|
||||
|
||||
# SPA 路由 fallback
|
||||
location / {
|
||||
try_files $uri $uri/ /index.html;
|
||||
}
|
||||
|
||||
# 静态资源缓存
|
||||
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
|
||||
expires 30d;
|
||||
add_header Cache-Control "public, immutable";
|
||||
}
|
||||
|
||||
# 禁止访问隐藏文件
|
||||
location ~ /\. {
|
||||
deny all;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user