12 KiB
Goal Planner Linux 部署指南
环境要求
服务器
- Linux 服务器(Ubuntu 20.04+ / CentOS 7+)
- Python 3.11+(由 uv 管理,不依赖系统 Python)
- MySQL 5.7+ / 8.0(需提前安装)
- Nginx(需提前安装)
- uv(Python 包管理工具)
关于 Python 版本:项目要求 Python ≥ 3.10。CentOS 7 系统自带 Python 2.7.5,无需升级或卸载,uv 会自动下载和管理独立的 Python 版本,不会与系统 Python 冲突。系统工具(如 yum)依赖的 Python 2.7.5 完全不受影响。推荐使用 Python 3.11,wheel 生态最成熟,所有依赖都有预编译 wheel,安装秒完成;Python 3.12/3.14 部分包(如 greenlet、pydantic-core)在 CentOS 7 上缺少兼容的预编译 wheel,需要从源码编译,而 CentOS 7 的 GCC 4.8.5 不支持 C++11,会导致编译失败。
本地(仅构建前端时需要)
- Node.js 18+
1. 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh
安装完成后,需要让 uv 命令生效(二选一):
# 方式一:执行以下命令(推荐,立即生效)
source $HOME/.local/bin/env
# 方式二:重新连接 SSH
验证安装:
uv --version
2. 配置 MySQL
# 登录 MySQL
sudo mysql -u root -p
# 创建数据库和用户
CREATE DATABASE goal_planner CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'goal_planner'@'localhost' IDENTIFIED BY '你的数据库密码';
GRANT ALL PRIVILEGES ON goal_planner.* TO 'goal_planner'@'localhost';
FLUSH PRIVILEGES;
EXIT;
首次启动后端时,SQLAlchemy 会自动创建表结构,无需手动导入。
3. 上传项目
将项目上传到服务器,部署目录为 /home/wwwroot/goal-planner:
sudo mkdir -p /home/wwwroot/goal-planner
# 方式一:git clone
cd /home/wwwroot/goal-planner
git clone <你的仓库地址> .
# 方式二:scp 上传
# scp -r ./goal-planner/* user@server:/home/wwwroot/goal-planner/
4. 后端部署
4.1 配置环境变量
cd /home/wwwroot/goal-planner/backend
cp .env.example .env
编辑 .env 文件:
vi .env
填入实际配置:
MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=goal_planner
MYSQL_PASSWORD=你的数据库密码
MYSQL_DATABASE=goal_planner
SECRET_KEY=替换为一个随机长字符串
ACCESS_TOKEN_EXPIRE_MINUTES=1440
LLM_PROVIDER=dashscope
OPENAI_API_KEY=你的API密钥
OPENAI_API_URL=https://dashscope.aliyuncs.com/compatible-mode/v1
OPENAI_MODEL=qwen3-plus
ENABLE_SEARCH=true
重要:
SECRET_KEY必须替换为随机字符串,可用openssl rand -hex 32生成。
4.2 使用 uv 创建虚拟环境并安装依赖
cd /home/wwwroot/goal-planner
# 创建虚拟环境,uv 会自动下载 Python 3.11(不依赖系统 Python)
uv venv .venv --python 3.11
# 激活虚拟环境
source .venv/bin/activate
# 安装依赖(使用清华镜像加速,强制只安装预编译 wheel)
uv pip install -r backend/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --only-binary :all:
说明:
uv venv --python 3.11会将 Python 3.11 下载到~/.local/share/uv/python/目录,仅 uv 使用,不会覆盖或修改系统自带的 Python 2.7.5。虚拟环境放在项目根目录/home/wwwroot/goal-planner/.venv,与 backend 同级。--only-binary :all:强制只安装预编译 wheel,避免在 CentOS 7 的旧 GCC 上从源码编译失败。
4.3 验证后端启动
cd /home/wwwroot/goal-planner/backend
source /home/wwwroot/goal-planner/.venv/bin/activate
uvicorn main:app --host 127.0.0.1 --port 8000
看到 Uvicorn running on http://127.0.0.1:8000 即启动成功,Ctrl+C 停止。
4.4 后台运行
验证无误后,使用以下方式后台运行(推荐方式二):
方式一:nohup(简单快速)
cd /home/wwwroot/goal-planner/backend
source /home/wwwroot/goal-planner/.venv/bin/activate
nohup uvicorn main:app --host 127.0.0.1 --port 8000 > /home/wwwroot/goal-planner/backend/app.log 2>&1 &
常用操作:
# 查看日志
tail -f /home/wwwroot/goal-planner/backend/app.log
# 查看进程
ps aux | grep uvicorn
# 停止服务
kill $(ps aux | grep 'uvicorn main:app' | grep -v grep | awk '{print $2}')
方式二:systemd 服务(推荐,开机自启 + 自动重启)
见第 7 章。
5. 前端构建与部署
5.1 修改 API 接口地址
前端 API 地址硬编码在 frontend/services/apiService.ts 中:
const API_BASE_URL = 'http://localhost:8000';
部署前必须修改为实际的后端地址。根据你的部署方式选择:
方式一:使用 Nginx 反向代理(推荐)
将 API 地址改为相对路径,由 Nginx 统一代理:
const API_BASE_URL = '/api-proxy';
这样前端请求 /api-proxy/api/generate/ 会被 Nginx 转发到后端 http://127.0.0.1:8000/api/generate/,无需暴露后端端口。
方式二:直接指向后端地址
如果你的后端运行在独立域名或端口上:
const API_BASE_URL = 'http://你的服务器IP:8000';
注意:此方式需要后端开放 8000 端口,并在
main.py的 CORS 配置中添加前端域名。
5.2 修改后端 CORS 配置(方式一不需要)
如果使用方式二,需要修改 backend/main.py 中的 CORS 允许来源:
origins = [
"http://你的域名",
"http://你的服务器IP",
]
5.3 本地构建前端
在本地开发机器上执行构建(不需要在服务器上安装 Node.js):
cd frontend
# 安装依赖
npm install
# 构建
npm run build
构建产物在 frontend/dist/ 目录中。
5.4 上传静态文件到服务器
将本地构建产物上传到服务器:
# 在本地执行
scp -r frontend/dist/* user@你的服务器IP:/var/www/goal-planner/
或在服务器上从项目目录复制(如果已上传整个项目):
sudo mkdir -p /var/www/goal-planner
sudo cp -r /home/wwwroot/goal-planner/frontend/dist/* /var/www/goal-planner/
6. 配置 Nginx
创建 Nginx 配置文件:
sudo vi /etc/nginx/conf.d/goal-planner.conf
方式一:Nginx 反向代理(推荐)
前后端统一通过 Nginx 访问,后端不对外暴露端口:
server {
listen 80;
server_name 你的域名或IP;
# 前端静态文件
root /var/www/goal-planner;
index index.html;
# 前端路由 - SPA 应用所有路径都返回 index.html
location / {
try_files $uri $uri/ /index.html;
}
# 后端 API 反向代理
location /api-proxy/ {
rewrite ^/api-proxy/(.*) /$1 break;
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;
# SSE 支持 - 关键配置
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 300s;
proxy_http_version 1.1;
proxy_set_header Connection '';
}
# 静态资源缓存
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
# 禁止访问隐藏文件
location ~ /\. {
deny all;
}
}
SSE 关键配置说明:
proxy_buffering off— 禁用缓冲,确保 SSE 事件实时推送到客户端proxy_cache off— 禁用缓存proxy_read_timeout 300s— AI 生成可能耗时较长,增大超时时间proxy_http_version 1.1+Connection ''— 保持长连接
方式二:前后端分离部署
后端直接监听 8000 端口对外服务:
server {
listen 80;
server_name 你的域名或IP;
root /var/www/goal-planner;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
location /assets/ {
expires 30d;
add_header Cache-Control "public, immutable";
}
}
此方式下 apiService.ts 中的 API_BASE_URL 应设为 http://你的域名或IP:8000。
验证并重启 Nginx
sudo nginx -t
sudo systemctl restart nginx
7. 使用 systemd 管理后端进程
创建 systemd 服务文件,实现开机自启和进程管理:
sudo vi /etc/systemd/system/goal-planner.service
[Unit]
Description=Goal Planner Backend API
After=network.target mysql.service
[Service]
Type=simple
User=root
WorkingDirectory=/home/wwwroot/goal-planner/backend
ExecStart=/home/wwwroot/goal-planner/.venv/bin/uvicorn main:app --host 127.0.0.1 --port 8000
Restart=always
RestartSec=5
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
如果使用方式二(前后端分离),将
--host 127.0.0.1改为--host 0.0.0.0以允许外部访问。
启动并设置开机自启:
sudo systemctl daemon-reload
sudo systemctl start goal-planner
sudo systemctl enable goal-planner
常用管理命令:
sudo systemctl status goal-planner # 查看状态
sudo systemctl restart goal-planner # 重启
sudo systemctl stop goal-planner # 停止
sudo journalctl -u goal-planner -f # 查看实时日志
8. 验证部署
# 检查后端健康状态
curl http://127.0.0.1:8000/api/health
# 预期返回: {"status":"ok"}
# 检查 Nginx 代理(方式一)
curl http://你的域名或IP/api-proxy/api/health
# 预期返回: {"status":"ok"}
# 浏览器访问
# http://你的域名或IP
9. HTTPS 配置(可选但推荐)
使用 Let's Encrypt 免费证书:
sudo apt install certbot python3-certbot-nginx # Ubuntu
sudo yum install certbot python3-certbot-nginx # CentOS
sudo certbot --nginx -d 你的域名
Certbot 会自动修改 Nginx 配置并配置 SSL 证书自动续期。
10. 更新部署
当代码更新后,执行以下步骤:
后端更新
# 服务器上拉取最新代码
cd /home/wwwroot/goal-planner
git pull
# 更新后端依赖(如有变动)
source /home/wwwroot/goal-planner/.venv/bin/activate
uv pip install -r backend/requirements.txt -i https://pypi.tuna.tsinghua.edu.cn/simple --only-binary :all:
# 重启后端
sudo systemctl restart goal-planner
前端更新
# 本地构建
cd frontend
npm install
npm run build
# 上传到服务器
scp -r dist/* user@你的服务器IP:/var/www/goal-planner/
文件结构总览
/home/wwwroot/goal-planner/
├── .venv/ # uv 创建的 Python 虚拟环境(项目根目录)
├── backend/
│ ├── .env # 环境变量配置(含数据库密码、API密钥)
│ ├── .env.example # 环境变量模板
│ ├── main.py # FastAPI 入口
│ ├── config.py # 配置读取
│ ├── database.py # 数据库连接
│ ├── requirements.txt # Python 依赖
│ ├── models/ # 数据模型
│ └── routes/ # API 路由
│ ├── auth.py
│ ├── generate.py
│ └── plans.py
└── frontend/
├── dist/ # 构建产物 → 部署到 /var/www/goal-planner/
├── services/
│ └── apiService.ts # API 地址配置(需修改 API_BASE_URL)
├── package.json
└── vite.config.ts
/var/www/goal-planner/ # Nginx 静态文件目录
/etc/nginx/conf.d/goal-planner.conf # Nginx 配置
/etc/systemd/system/goal-planner.service # 后端服务配置