Files
JuYou/文档/部署文档.md
2026-08-25 17:59:42 +08:00

520 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 剧核工厂生产环境部署文档
本文档适用于在 Windows 本地构建项目,并一键部署到 Linux AMD64 服务器。
这里的“一键部署”是指服务器上的 `one_click_deployment.sh` 会一次完成环境初始化、数据库迁移、服务注册、Nginx 和 HTTPS 配置。
完整发布分为两个明确阶段:本地构建并上传、服务器执行一键部署。`push.bat` 只上传文件,不会自动修改数据库或重启线上服务。
## 1. 最短操作流程
首次部署,在 Windows 项目根目录执行:
```powershell
.\API\deploy\push.bat root@服务器IP with-env
ssh root@服务器IP
sudo bash /opt/juyou_ai/deploy/one_click_deployment.sh
```
日常更新,在 Windows 项目根目录执行:
```powershell
.\API\deploy\push.bat root@服务器IP
ssh root@服务器IP
sudo bash /opt/juyou_ai/deploy/one_click_deployment.sh
```
首次部署使用 `with-env`,将本地正式环境配置送到服务器;日常更新不使用 `with-env`,继续保留服务器已有的生产配置。
上传和服务器部署是两个独立步骤,便于在执行数据库迁移和重启前安排备份与维护窗口。
## 2. 固定路径与服务
| 项目 | 固定值 |
| --- | --- |
| 服务器项目目录 | `/opt/juyou_ai` |
| API 二进制 | `/opt/juyou_ai/bin/jcf-api` |
| 部署脚本 | `/opt/juyou_ai/deploy/one_click_deployment.sh` |
| WEB 静态目录 | `/opt/juyou_ai/static/web` |
| ADMIN 静态目录 | `/opt/juyou_ai/static/admin` |
| 数据库迁移目录 | `/opt/juyou_ai/migrations` |
| systemd 服务名 | `juyou_ai` |
| API 内部监听地址 | `127.0.0.1:8123` |
| 生产环境文件 | `/etc/juyou_ai/juyou_ai.env` |
| 临时环境文件 | `/tmp/juyou_ai.env` |
| Whisper 离线模型 | `/opt/juyou_ai/models/faster-whisper-small` |
| Whisper 运行缓存 | `/var/cache/juyou_ai/huggingface` |
| Nginx 配置 | `/etc/nginx/conf.d/juyou_ai.conf` |
| SSL 证书目录 | `/etc/nginx/ssl` |
API 仅监听服务器本机地址,公网请求统一通过 Nginx 进入。
## 3. 首次部署
### 3.1 准备本地环境
本地需要安装:
- Node.js 和 npm
- Go
- Python 3;服务器缺少离线模型时,本机还需要 `faster-whisper`
- tar
- OpenSSH Client`ssh``scp`
在终端确认命令可用:
```powershell
npm --version
go version
python --version
tar --version
ssh -V
```
首次在本机下载 Whisper 模型前安装 Python 依赖:
```powershell
python -m pip install faster-whisper==1.2.1
```
`push.bat` 不会自动安装前端依赖。首次构建或 `package-lock.json` 发生变化后,先执行:
```powershell
npm --prefix WEB ci
npm --prefix ADMIN ci
```
首次部署使用的正式环境配置保存在本地:
```text
API/.env
```
至少确认以下字段使用正式值,不能保留 `replace-with``change-me``example.com` 或开发环境默认值:
```env
DATABASE_NAME=juchuang_factory
DATABASE_USER=jcf
DATABASE_PASSWORD=数据库强密码
JWT_SECRET_KEY=随机长密钥
ADMIN_BOOTSTRAP_USERNAME=admin
ADMIN_BOOTSTRAP_PASSWORD=管理员初始强密码
CONFIG_ENCRYPTION_KEY_VERSION=v1
CONFIG_ENCRYPTION_KEY=正式加密密钥
COS_SECRET_ID=腾讯云子账号SecretId
COS_SECRET_KEY=腾讯云子账号SecretKey
COS_BUCKET=juyouai-1451538162
COS_REGION=ap-chengdu
COS_ENDPOINT=https://cos.ap-chengdu.myqcloud.com
COS_PUBLIC_BASE_URL=https://cos.youjuhui.xyz
```
COS 媒体使用独立域名时,还必须在腾讯云控制台进入 **对象存储 COS → 对应存储桶 → 安全管理 → 跨域访问 CORS 设置**,添加以下规则。将域名替换为实际访问 WEB 的域名;多个 WEB 域名需要全部列出。
```json
[
{
"AllowedOrigins": [
"https://juhefactory.com",
"https://www.juhefactory.com"
],
"AllowedMethods": [
"GET",
"HEAD"
],
"AllowedHeaders": [
"*"
],
"ExposeHeaders": [
"Accept-Ranges",
"Content-Length",
"Content-Range",
"Content-Type",
"ETag"
],
"MaxAgeSeconds": 3600
}
]
```
保存策略后,确认媒体响应包含与当前 WEB 域名一致的 `Access-Control-Allow-Origin`。否则视频可以播放,但浏览器会禁止导出静帧和通过 Blob 直接下载。
可以使用以下命令生成随机密钥:
```bash
openssl rand -hex 32
```
### 3.2 准备服务器
目标服务器需要满足:
- Linux AMD64/x86_64,使用 Debian 或 Ubuntu 最稳妥
- 使用 systemd
- SSH 登录用户具备 sudo 权限,推荐使用 root
- 云安全组及防火墙已放行 TCP 80、443
- 启用 HTTPS 时,域名已经解析到服务器公网 IP
脚本虽然包含 `apt-get``dnf``yum` 的安装分支,但服务账户固定使用 `www-data`。使用非 Debian/Ubuntu 发行版前,需要先确认系统存在 `www-data` 用户和用户组,并确认 PostgreSQL、Redis 的 systemd 服务名与脚本兼容。
### 3.3 本地构建并上传
在 Windows 项目根目录执行:
```powershell
.\API\deploy\push.bat root@服务器IP with-env
```
示例:
```powershell
.\API\deploy\push.bat root@192.168.1.1 with-env
```
命令完成并显示以下内容后,才进入服务器执行部署:
```text
Deployment push complete.
```
本地上传完成只表示文件已经同步到 `/opt/juyou_ai`,此时不会自动安装依赖、迁移数据库或重启服务。
### 3.4 登录服务器并执行首次部署
本地另行登录服务器:
```powershell
ssh root@服务器IP
```
服务器上执行:
```bash
bash /opt/juyou_ai/deploy/one_click_deployment.sh
```
如果当前不是 root 用户,执行:
```bash
sudo bash /opt/juyou_ai/deploy/one_click_deployment.sh
```
首次运行会询问两项配置。
域名:
```text
juhefactory.com
```
多个域名使用空格分隔:
```text
juhefactory.com www.juhefactory.com
```
不申请 SSL 时输入:
```text
_
```
然后输入 SSL 证书邮箱;不申请 SSL 时直接回车。域名和邮箱会保存到:
```text
/opt/juyou_ai/deploy/.deploy.conf
```
首次部署完成后,将该文件复制到本地:
```powershell
scp root@服务器IP:/opt/juyou_ai/deploy/.deploy.conf .\API\deploy\.deploy.conf
```
后续上传不会携带本地 `.deploy.conf`;服务器会继续使用 `/opt/juyou_ai/deploy/.deploy.conf`,不会被本地文件覆盖。
### 3.5 验证首次部署
查看服务状态:
```bash
systemctl status juyou_ai --no-pager
systemctl status nginx --no-pager
systemctl status postgresql --no-pager
systemctl status redis-server --no-pager
```
检查 API
```bash
curl -i http://127.0.0.1:8123/health
```
启用 HTTPS 后检查公网入口:
```bash
curl -i https://你的域名/health
```
页面地址:
```text
https://你的域名/
https://你的域名/admin/
```
## 4. 更新部署
每次更新都分为本地上传和服务器部署两步,不能只执行其中一步。
### 4.1 本地重新构建并上传
在 Windows 项目根目录执行:
```powershell
.\API\deploy\push.bat root@服务器IP
```
等待出现:
```text
Deployment push complete.
```
### 4.2 服务器应用更新
登录服务器:
```powershell
ssh root@服务器IP
```
执行:
```bash
bash /opt/juyou_ai/deploy/one_click_deployment.sh
```
更新部署会:
- 继续使用服务器现有的 `/etc/juyou_ai/juyou_ai.env`
- 执行尚未执行的数据库迁移
- 更新 systemd 与 Nginx 配置
- 重启 systemd 服务 `juyou_ai`
### 4.3 只更新已上传文件但暂不部署
只执行本地 `push.bat` 即可。上传完成后不要在服务器运行 `one_click_deployment.sh`
此时:
- `/opt/juyou_ai` 中已经是新文件
- `/etc/juyou_ai/juyou_ai.env` 保持不变
- 当前运行中的 API 进程仍可能使用旧二进制
- 数据库迁移、Nginx 更新和服务重启均未执行
需要正式应用更新时,再执行服务器部署命令。
## 5. 推送参数说明
| 命令 | 是否上传 `API/.env` | 是否自动执行服务器部署 | 使用场景 |
| --- | --- | --- | --- |
| `push.bat root@服务器IP` | 否 | 否 | 日常增量更新 |
| `push.bat root@服务器IP stage-only` | 否 | 否 | 与默认推送行为相同,用于明确表达“只暂存” |
| `push.bat root@服务器IP with-env` | 是 | 否 | 首次部署或明确替换整套生产环境配置 |
三种命令都只负责构建、打包和上传。`stage-only` 当前是语义标记,执行行为与不传第二个参数相同。只有随后在服务器运行 `one_click_deployment.sh`,才会执行迁移、更新服务配置并重启应用。
## 6. 常用维护命令
服务管理:
```bash
systemctl restart juyou_ai
systemctl stop juyou_ai
systemctl start juyou_ai
systemctl reload nginx
nginx -t
```
查看 API 日志:
```bash
journalctl -u juyou_ai -f
journalctl -u juyou_ai -n 200 --no-pager
```
修改域名或证书邮箱:
```bash
nano /opt/juyou_ai/deploy/.deploy.conf
```
也可以删除配置,让下次部署重新询问:
```bash
rm /opt/juyou_ai/deploy/.deploy.conf
```
更新 acme.sh
```bash
bash /opt/juyou_ai/deploy/update_acme.sh
```
## 7. 备份与故障排查
正式执行数据库迁移前应先备份数据库。以下示例中的数据库名必须替换为生产环境 `DATABASE_NAME` 的实际值:
```bash
mkdir -p /opt/juyou_ai/backups
sudo -u postgres pg_dump -Fc juchuang_factory | tee /opt/juyou_ai/backups/juchuang_factory.dump >/dev/null
```
PostgreSQL
```bash
systemctl status postgresql --no-pager
journalctl -u postgresql -n 200 --no-pager
```
Redis
```bash
systemctl status redis-server --no-pager
redis-cli ping
```
Nginx
```bash
nginx -t
journalctl -u nginx -n 200 --no-pager
```
API
```bash
systemctl status juyou_ai --no-pager
journalctl -u juyou_ai -n 200 --no-pager
ls -l /etc/juyou_ai/juyou_ai.env
ls -l /opt/juyou_ai/bin/jcf-api
```
如果部署提示环境字段缺失、格式错误或仍为示例值,修改本地 `API/.env`,重新执行 `push.bat`,然后再次在服务器运行部署脚本。
如果数据库迁移失败,应先核对数据库实际结构和 `jcf_schema_migrations`,不得通过手工插入迁移记录直接绕过错误。数据库迁移不会自动回滚。
## 8. 自动化部署流程说明
本节用于解释脚本内部做了什么。日常操作只需要按“首次部署”或“更新部署”章节执行命令。
### 8.1 `push.bat` 的本地流程
1. 检查目标 SSH 地址;仅在使用 `with-env` 时检查本地 `API/.env` 是否存在。
2. 通过 SSH 检查服务器是否已有完整的 Whisper `small` 模型。缺少时,本机运行 `download_whisper_model.py` 下载模型,并把 `models/` 加入本次上传包。
3. 执行 `npm --prefix WEB run build`,类型检查通过后将 WEB 输出到 `API/static/web`
4. 执行 `npm --prefix ADMIN run build`,类型检查通过后将 ADMIN 输出到 `API/static/admin`
5. 使用 `GOOS=linux``GOARCH=amd64``-trimpath` 和裁剪调试信息的链接参数,编译 `API/bin/jcf-api`
6. 创建本机临时压缩包,包含:
```text
bin/
static/
deploy/
migrations/
acme/
workers/
models/ # 仅服务器缺少离线模型时包含
.env # 仅使用 with-env 时包含
```
7. 使用 SCP 将压缩包上传到 `/tmp/juyou-deploy.tar.gz`
8. 使用 SSH 在服务器的 `/tmp/juyou-deploy-work` 临时目录解包。
9. 默认删除可能残留的 `/tmp/juyou_ai.env`;使用 `with-env` 时才将 `.env` 安装为权限 `600``/tmp/juyou_ai.env`,并从项目文件中删除 `.env`
10. 服务器存在 `rsync` 时,以 `--delete` 将发布文件同步到 `/opt/juyou_ai`;不存在时使用 `cp -a` 覆盖复制。
11. 删除服务器临时解包目录和压缩包。
12. 删除本机临时压缩包。
同步时保留以下服务器内容:
```text
/opt/juyou_ai/media/
/opt/juyou_ai/backups/
/opt/juyou_ai/models/
```
`models/` 默认不会被 `rsync --delete` 清理;仅当服务器缺少完整模型且本次压缩包含有模型时,才会单独同步模型内容。
`/opt/juyou_ai/deploy/.deploy.conf` 仅在服务器首次运行部署脚本时生成;上传包会排除本地 `.deploy.conf`,后续部署不会覆盖服务器配置。
`.go` 源码、测试代码、`cmd``internal``tools``media``backups` 不会进入上传包;运行时需要的 `workers` 会进入上传包。
### 8.2 `one_click_deployment.sh` 的服务器流程
1. 首次运行时只从 JuYouAI 自己的 Nginx 配置恢复域名;没有该配置时询问域名。仅复用输入域名对应的证书和私钥,不扫描其他项目的证书,并保存 `.deploy.conf`
2. 使用 `with-env` 时检测 `/tmp/juyou_ai.env` 并将其作为本次环境配置来源,否则继续使用服务器生产环境文件。
3. 调用 `deploy_with_ssl.sh` 执行正式部署。
### 8.3 `deploy_with_ssl.sh` 和 `prepare_server.sh` 的服务器流程
1. 本机执行 `push.bat` 时检查服务器是否已有 Whisper 模型;首次部署会在本机下载并上传到 `/opt/juyou_ai/models/faster-whisper-small`。服务器不访问 Hugging Face。
2. 安装 sudo、Nginx、PostgreSQL、Redis、FFmpeg、curl、socat、ca-certificates、openssl、Python 3 和 pip;缺少时安装 `faster-whisper 1.2.1`
3. 启用并启动 PostgreSQL、Redis 和 Nginx。
4. 存在 `/tmp/juyou_ai.env` 时将其安装到 `/etc/juyou_ai/juyou_ai.env`;否则保留现有生产环境文件,权限保持 `root:root``600`
5. 将生产环境标准化为:
```env
APP_ENV=production
DEBUG=false
SERVER_ADDRESS=127.0.0.1:8123
DATABASE_HOST=127.0.0.1
DATABASE_PORT=5432
DATABASE_URL=
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
CORS_ORIGINS=根据部署域名生成
FFMPEG_PATH=ffmpeg
FFPROBE_PATH=ffprobe
PYTHON_PATH=python3
ASR_SCRIPT_PATH=/opt/juyou_ai/workers/transcribe.py
JCF_ASR_CACHE_DIR=/var/cache/juyou_ai
HF_HOME=/var/cache/juyou_ai/huggingface
FASTER_WHISPER_MODEL_PATH=/opt/juyou_ai/models/faster-whisper-small
```
6. 校验离线 Whisper 模型、数据库、JWT、管理员、配置加密和 COS 等必填配置。
7. 创建或更新 PostgreSQL 用户和数据库,配置本机认证。
8. 按文件名顺序执行 `/opt/juyou_ai/migrations/*.up.sql`,并记录到 `jcf_schema_migrations`
9. 创建或更新 `/etc/systemd/system/juyou_ai.service`
```ini
[Service]
User=www-data
Group=www-data
WorkingDirectory=/opt/juyou_ai
EnvironmentFile=/etc/juyou_ai/juyou_ai.env
CacheDirectory=juyou_ai
ExecStart=/opt/juyou_ai/bin/jcf-api
Restart=always
RestartSec=3
```
10. 配置 Nginx`/api/` 和健康检查路径代理到 `127.0.0.1:8123``/admin/` 提供 ADMIN 静态文件,其他路径提供 WEB 静态文件,上传体积上限为 2 GiB。
11. 配置域名且已有该域名的证书时直接复用;没有证书但填写邮箱时,先创建 HTTP 验证站点,再使用 acme.sh 通过 HTTP-01 申请并安装 HTTPS 证书;域名填 `_`,或没有证书且未填写邮箱时使用 HTTP。
12. 启用 HTTPS 时把 80 端口请求重定向到 HTTPS,并允许 TLS 1.2、TLS 1.3。
13. 执行 `nginx -t`,配置检查成功后重载 Nginx。
14. 重启 systemd 服务 `juyou_ai`
15. 部署成功后删除 `/tmp/juyou_ai.env`
如果部署中途失败,临时环境文件可能保留,以便排查并重新执行部署;问题解决并部署成功后会自动清理。
### 8.4 重复执行与失败边界
- 脚本使用 `set -euo pipefail`,关键命令失败时会立即退出。
- 已有 PostgreSQL 用户会更新密码,已有数据库不会重复创建。
- 已记录在 `jcf_schema_migrations` 的迁移会跳过,未记录迁移按文件名顺序执行。
- systemd 和 Nginx 配置每次都会按当前发布内容重新生成。
- 已保存的域名、证书邮箱和匹配域名的现有证书会复用。
- 部署脚本不会自动恢复旧二进制,也不会自动回滚已经成功执行的数据库迁移。发布前必须自行完成数据库备份;需要应用级回滚时,应重新上传兼容当前数据库结构的旧版本并再次部署。