16 KiB
剧核工厂生产环境部署文档
本文档适用于在 Windows 本地构建项目,并一键部署到 Linux AMD64 服务器。
这里的“一键部署”是指服务器上的 one_click_deployment.sh 会一次完成环境初始化、数据库迁移、服务注册、Nginx 和 HTTPS 配置。
完整发布分为两个明确阶段:本地构建并上传、服务器执行一键部署。push.bat 只上传文件,不会自动修改数据库或重启线上服务。
1. 最短操作流程
首次部署,在 Windows 项目根目录执行:
.\API\deploy\push.bat root@服务器IP with-env
ssh root@服务器IP
sudo bash /opt/juyou_ai/deploy/one_click_deployment.sh
日常更新,在 Windows 项目根目录执行:
.\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)
在终端确认命令可用:
npm --version
go version
python --version
tar --version
ssh -V
首次在本机下载 Whisper 模型前安装 Python 依赖:
python -m pip install faster-whisper==1.2.1
push.bat 不会自动安装前端依赖。首次构建或 package-lock.json 发生变化后,先执行:
npm --prefix WEB ci
npm --prefix ADMIN ci
首次部署使用的正式环境配置保存在本地:
API/.env
至少确认以下字段使用正式值,不能保留 replace-with、change-me、example.com 或开发环境默认值:
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 域名需要全部列出。
[
{
"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 直接下载。
可以使用以下命令生成随机密钥:
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 项目根目录执行:
.\API\deploy\push.bat root@服务器IP with-env
示例:
.\API\deploy\push.bat root@192.168.1.1 with-env
命令完成并显示以下内容后,才进入服务器执行部署:
Deployment push complete.
本地上传完成只表示文件已经同步到 /opt/juyou_ai,此时不会自动安装依赖、迁移数据库或重启服务。
3.4 登录服务器并执行首次部署
本地另行登录服务器:
ssh root@服务器IP
服务器上执行:
bash /opt/juyou_ai/deploy/one_click_deployment.sh
如果当前不是 root 用户,执行:
sudo bash /opt/juyou_ai/deploy/one_click_deployment.sh
首次运行会询问两项配置。
域名:
juhefactory.com
多个域名使用空格分隔:
juhefactory.com www.juhefactory.com
不申请 SSL 时输入:
_
然后输入 SSL 证书邮箱;不申请 SSL 时直接回车。域名和邮箱会保存到:
/opt/juyou_ai/deploy/.deploy.conf
首次部署完成后,将该文件复制到本地:
scp root@服务器IP:/opt/juyou_ai/deploy/.deploy.conf .\API\deploy\.deploy.conf
后续上传不会携带本地 .deploy.conf;服务器会继续使用 /opt/juyou_ai/deploy/.deploy.conf,不会被本地文件覆盖。
3.5 验证首次部署
查看服务状态:
systemctl status juyou_ai --no-pager
systemctl status nginx --no-pager
systemctl status postgresql --no-pager
systemctl status redis-server --no-pager
检查 API:
curl -i http://127.0.0.1:8123/health
启用 HTTPS 后检查公网入口:
curl -i https://你的域名/health
页面地址:
https://你的域名/
https://你的域名/admin/
4. 更新部署
每次更新都分为本地上传和服务器部署两步,不能只执行其中一步。
4.1 本地重新构建并上传
在 Windows 项目根目录执行:
.\API\deploy\push.bat root@服务器IP
等待出现:
Deployment push complete.
4.2 服务器应用更新
登录服务器:
ssh root@服务器IP
执行:
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. 常用维护命令
服务管理:
systemctl restart juyou_ai
systemctl stop juyou_ai
systemctl start juyou_ai
systemctl reload nginx
nginx -t
查看 API 日志:
journalctl -u juyou_ai -f
journalctl -u juyou_ai -n 200 --no-pager
修改域名或证书邮箱:
nano /opt/juyou_ai/deploy/.deploy.conf
也可以删除配置,让下次部署重新询问:
rm /opt/juyou_ai/deploy/.deploy.conf
更新 acme.sh:
bash /opt/juyou_ai/deploy/update_acme.sh
7. 备份与故障排查
正式执行数据库迁移前应先备份数据库。以下示例中的数据库名必须替换为生产环境 DATABASE_NAME 的实际值:
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:
systemctl status postgresql --no-pager
journalctl -u postgresql -n 200 --no-pager
Redis:
systemctl status redis-server --no-pager
redis-cli ping
Nginx:
nginx -t
journalctl -u nginx -n 200 --no-pager
API:
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 的本地流程
- 检查目标 SSH 地址;仅在使用
with-env时检查本地API/.env是否存在。 - 通过 SSH 检查服务器是否已有完整的 Whisper
small模型。缺少时,本机运行download_whisper_model.py下载模型,并把models/加入本次上传包。 - 执行
npm --prefix WEB run build,类型检查通过后将 WEB 输出到API/static/web。 - 执行
npm --prefix ADMIN run build,类型检查通过后将 ADMIN 输出到API/static/admin。 - 使用
GOOS=linux、GOARCH=amd64、-trimpath和裁剪调试信息的链接参数,编译API/bin/jcf-api。 - 创建本机临时压缩包,包含:
bin/
static/
deploy/
migrations/
acme/
workers/
models/ # 仅服务器缺少离线模型时包含
.env # 仅使用 with-env 时包含
- 使用 SCP 将压缩包上传到
/tmp/juyou-deploy.tar.gz。 - 使用 SSH 在服务器的
/tmp/juyou-deploy-work临时目录解包。 - 默认删除可能残留的
/tmp/juyou_ai.env;使用with-env时才将.env安装为权限600的/tmp/juyou_ai.env,并从项目文件中删除.env。 - 服务器存在
rsync时,以--delete将发布文件同步到/opt/juyou_ai;不存在时使用cp -a覆盖复制。 - 删除服务器临时解包目录和压缩包。
- 删除本机临时压缩包。
同步时保留以下服务器内容:
/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 的服务器流程
- 首次运行时只从 JuYouAI 自己的 Nginx 配置恢复域名;没有该配置时询问域名。仅复用输入域名对应的证书和私钥,不扫描其他项目的证书,并保存
.deploy.conf。 - 使用
with-env时检测/tmp/juyou_ai.env并将其作为本次环境配置来源,否则继续使用服务器生产环境文件。 - 调用
deploy_with_ssl.sh执行正式部署。
8.3 deploy_with_ssl.sh 和 prepare_server.sh 的服务器流程
- 本机执行
push.bat时检查服务器是否已有 Whisper 模型;首次部署会在本机下载并上传到/opt/juyou_ai/models/faster-whisper-small。服务器不访问 Hugging Face。 - 安装 sudo、Nginx、PostgreSQL、Redis、FFmpeg、curl、socat、ca-certificates、openssl、Python 3 和 pip;缺少时安装
faster-whisper 1.2.1。 - 启用并启动 PostgreSQL、Redis 和 Nginx。
- 存在
/tmp/juyou_ai.env时将其安装到/etc/juyou_ai/juyou_ai.env;否则保留现有生产环境文件,权限保持root:root、600。 - 将生产环境标准化为:
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
- 校验离线 Whisper 模型、数据库、JWT、管理员、配置加密和 COS 等必填配置。
- 创建或更新 PostgreSQL 用户和数据库,配置本机认证。
- 按文件名顺序执行
/opt/juyou_ai/migrations/*.up.sql,并记录到jcf_schema_migrations。 - 创建或更新
/etc/systemd/system/juyou_ai.service:
[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
- 配置 Nginx:
/api/和健康检查路径代理到127.0.0.1:8123,/admin/提供 ADMIN 静态文件,其他路径提供 WEB 静态文件,上传体积上限为 2 GiB。 - 配置域名且已有该域名的证书时直接复用;没有证书但填写邮箱时,先创建 HTTP 验证站点,再使用 acme.sh 通过 HTTP-01 申请并安装 HTTPS 证书;域名填
_,或没有证书且未填写邮箱时使用 HTTP。 - 启用 HTTPS 时把 80 端口请求重定向到 HTTPS,并允许 TLS 1.2、TLS 1.3。
- 执行
nginx -t,配置检查成功后重载 Nginx。 - 重启 systemd 服务
juyou_ai。 - 部署成功后删除
/tmp/juyou_ai.env。
如果部署中途失败,临时环境文件可能保留,以便排查并重新执行部署;问题解决并部署成功后会自动清理。
8.4 重复执行与失败边界
- 脚本使用
set -euo pipefail,关键命令失败时会立即退出。 - 已有 PostgreSQL 用户会更新密码,已有数据库不会重复创建。
- 已记录在
jcf_schema_migrations的迁移会跳过,未记录迁移按文件名顺序执行。 - systemd 和 Nginx 配置每次都会按当前发布内容重新生成。
- 已保存的域名、证书邮箱和匹配域名的现有证书会复用。
- 部署脚本不会自动恢复旧二进制,也不会自动回滚已经成功执行的数据库迁移。发布前必须自行完成数据库备份;需要应用级回滚时,应重新上传兼容当前数据库结构的旧版本并再次部署。