Files
zhimingge/docs/DEPLOY.md
T
dekun fff77dac3f Implement three divination modes, learn pages, and PM2 deploy on port 3130.
Add liuyao/bazi/combined flows with shared calc and AI infrastructure, 64-gua learn routes, and update Ubuntu PM2 deployment docs for port 3130.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 20:19:49 +08:00

459 lines
10 KiB
Markdown
Raw 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.
# 知命阁(zhiminggeUbuntu 部署文档
> 仓库:[https://git.bz121.com/dekun/zhimingge.git](https://git.bz121.com/dekun/zhimingge.git)
本文档说明在 **Ubuntu 服务器**上使用 **root 用户**、**PM2** 将知命阁部署到 **`/opt/zhimingge`** 的完整流程。
---
## 1. 部署架构
```
┌─────────────────┐
用户浏览器 ──→ │ Nginx (可选) │ :80 / :443
│ 反向代理 │
└────────┬────────┘
┌────────▼────────┐
│ PM2 │
│ zhimingge │ :3130
└────────┬────────┘
┌────────▼────────┐
│ Next.js │
│ standalone │
│ /opt/zhimingge │
└─────────────────┘
┌────────▼────────┐
│ op.bz121.com │ AI API
│ /v1 │
└─────────────────┘
```
| 组件 | 说明 |
|------|------|
| 操作系统 | Ubuntu 20.04 / 22.04 / 24.04 LTS |
| 运行用户 | root(按需求) |
| 安装目录 | `/opt/zhimingge` |
| 进程管理 | PM2 |
| 构建模式 | Next.js `output: "standalone"` |
| 默认端口 | **3130** |
---
## 2. 服务器要求
| 项目 | 最低配置 | 推荐配置 |
|------|----------|----------|
| CPU | 1 核 | 2 核 |
| 内存 | 1 GB | 2 GB+ |
| 磁盘 | 2 GB | 10 GB |
| 网络 | 可访问 git.bz121.com、op.bz121.com | — |
---
## 3. 一次性环境准备
**root** 登录服务器后执行:
### 3.1 更新系统
```bash
apt update && apt upgrade -y
```
### 3.2 安装 Node.js 20(推荐 LTS
```bash
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
node -v # 应 >= v20
npm -v
```
### 3.3 安装 pnpm 与 PM2
```bash
npm install -g pnpm pm2
pnpm -v
pm2 -v
```
### 3.4 安装 Git
```bash
apt install -y git
```
### 3.5(可选)安装 Nginx 反向代理
若需域名 + HTTPS,建议安装 Nginx 与 Certbot
```bash
apt install -y nginx certbot python3-certbot-nginx
```
---
## 4. 克隆与目录
```bash
mkdir -p /opt
cd /opt
# 首次克隆(私有仓库需配置凭据,见第 5 节)
git clone https://git.bz121.com/dekun/zhimingge.git zhimingge
cd /opt/zhimingge
```
最终目录:
```
/opt/zhimingge/
├── app/
├── content/
├── ecosystem.config.cjs
├── .env.local ← 生产环境变量(勿提交 Git)
├── package.json
└── ...
```
---
## 5. Git 凭据(私有仓库)
仓库 [dekun/zhimingge](https://git.bz121.com/dekun/zhimingge.git) 为私有仓库,克隆前需配置认证。
### 方式 A:HTTPS + 访问令牌(推荐)
```bash
git config --global credential.helper store
git clone https://git.bz121.com/dekun/zhimingge.git /opt/zhimingge
# 按提示输入 Gitea 用户名与 Personal Access Token
```
在 Gitea 生成 Token:用户设置 → Applications → Generate New Token(勾选 `repo` 权限)。
### 方式 BSSH
```bash
ssh-keygen -t ed25519 -C "zhimingge-deploy" -f /root/.ssh/zhimingge -N ""
cat /root/.ssh/zhimingge.pub
# 将公钥添加到 Gitea → Settings → SSH Keys
cat >> /root/.ssh/config << 'EOF'
Host git.bz121.com
IdentityFile /root/.ssh/zhimingge
StrictHostKeyChecking accept-new
EOF
git clone git@git.bz121.com:dekun/zhimingge.git /opt/zhimingge
```
---
## 6. 环境变量
```bash
cd /opt/zhimingge
cp .env.example .env.local
nano .env.local
```
**`.env.local` 示例:**
```env
# AI 接口(必填)
OPENAI_API_KEY=你的密钥
# AI 地址与模型(已有默认值,可按需覆盖)
OPENAI_BASE_URL=https://op.bz121.com/v1
OPENAI_MODEL=huihui_ai/gemma-4-abliterated:e4b
# 服务端口(与 PM2 ecosystem.config.cjs 一致)
PORT=3130
NODE_ENV=production
```
保存后限制权限:
```bash
chmod 600 .env.local
```
---
## 7. 构建与启动
### 7.1 安装依赖
```bash
cd /opt/zhimingge
pnpm install --frozen-lockfile
```
### 7.2 生产构建
```bash
pnpm run build
```
构建成功后生成 `.next/standalone/` 独立运行包。
### 7.3 复制静态资源(standalone 必需)
Next.js standalone 模式需手动链接静态文件:
```bash
cd /opt/zhimingge
# 复制 static 与 public 到 standalone 目录
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
# 复制内容库(服务端读取卦辞 Markdown)
cp -r content .next/standalone/content
```
> **说明**:若应用从项目根目录读取 `content/`PM2 的 `cwd` 应设为 `/opt/zhimingge` 而非 standalone 子目录。当前 `ecosystem.config.cjs` 使用项目根目录 + `pnpm start`,构建后也可改用 standalone 的 `server.js`(见 7.5 备选方案)。
### 7.4 使用 PM2 启动(推荐方式)
项目根目录已包含 `ecosystem.config.cjs`
```bash
cd /opt/zhimingge
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup
# 按 PM2 提示执行生成的命令,确保开机自启
```
常用 PM2 命令:
```bash
pm2 status # 查看状态
pm2 logs zhimingge # 查看日志
pm2 restart zhimingge # 重启
pm2 stop zhimingge # 停止
pm2 delete zhimingge # 删除进程
```
### 7.5 备选:standalone 直接运行
若希望仅运行 standalone 产物(体积更小):
```bash
cd /opt/zhimingge/.next/standalone
PORT=3130 node server.js
```
对应 PM2 配置片段:
```javascript
{
name: "zhimingge",
cwd: "/opt/zhimingge/.next/standalone",
script: "server.js",
env: {
PORT: 3130,
NODE_ENV: "production",
},
}
```
此时需确保 `content/``public/` 路径在代码中相对于 `cwd` 可访问。
### 7.6 验证
```bash
curl -I http://127.0.0.1:3130
# 应返回 HTTP/1.1 200
```
浏览器访问:`http://服务器IP:3130`
---
## 8. Nginx 反向代理(可选)
假设域名为 `zhimingge.example.com`
```bash
nano /etc/nginx/sites-available/zhimingge
```
```nginx
server {
listen 80;
server_name zhimingge.example.com;
location / {
proxy_pass http://127.0.0.1:3130;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
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_cache_bypass $http_upgrade;
# AI 流式响应需禁用缓冲
proxy_buffering off;
proxy_read_timeout 300s;
}
}
```
```bash
ln -s /etc/nginx/sites-available/zhimingge /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
# HTTPSLet's Encrypt
certbot --nginx -d zhimingge.example.com
```
---
## 9. 更新部署流程
代码推送至 Gitea 后,在服务器执行:
```bash
cd /opt/zhimingge
# 拉取最新代码
git pull origin main
# 安装新依赖(如有变更)
pnpm install --frozen-lockfile
# 重新构建
pnpm run build
# 若使用 standalone 复制方式,重新复制 static/public/content
cp -r .next/static .next/standalone/.next/static
cp -r public .next/standalone/public
cp -r content .next/standalone/content
# 重启
pm2 restart zhimingge
```
可写入脚本 `/opt/zhimingge/scripts/deploy.sh` 一键执行(见项目内脚本)。
---
## 10. 防火墙
若使用 UFW
```bash
# 仅 Nginx 对外(推荐)
ufw allow 22
ufw allow 80
ufw allow 443
ufw enable
# 若不用 Nginx,直接暴露 3130
ufw allow 3130
```
---
## 11. 日志与排错
### PM2 日志
```bash
pm2 logs zhimingge --lines 100
```
日志文件位置(默认):
```
/root/.pm2/logs/zhimingge-out.log
/root/.pm2/logs/zhimingge-error.log
```
### 常见问题
| 现象 | 可能原因 | 处理 |
|------|----------|------|
| 502 Bad Gateway | PM2 进程未运行 | `pm2 restart zhimingge` |
| AI 解读失败 | API Key 错误或模型名不对 | 检查 `.env.local` |
| 卦辞读取失败 | `content/` 路径不存在 | 确认 `content/zhouyi/docs/` 存在 |
| 构建 OOM | 内存不足 | 增加 swap 或升级内存 |
| 流式输出中断 | Nginx 缓冲 | 设置 `proxy_buffering off` |
| Git pull 失败 | 凭据过期 | 重新配置 Token 或 SSH |
### 构建内存不足时增加 Swap
```bash
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
```
### 测试 AI 接口
```bash
curl https://op.bz121.com/v1/models \
-H "Authorization: Bearer 你的OPENAI_API_KEY"
```
确认返回列表中包含 `huihui_ai/gemma-4-abliterated:e4b`
---
## 12. 安全建议
虽然当前按 **root** 部署,仍建议:
1. **`.env.local` 权限** 设为 `600`,勿提交 Git
2. **API Key** 仅保存在服务器,不要写入前端代码
3. 生产环境使用 **Nginx + HTTPS**
4. 定期 `apt update``pnpm update`
5. 若后续改为非 root 运行,创建专用用户:
```bash
useradd -r -s /bin/false zhimingge
chown -R zhimingge:zhimingge /opt/zhimingge
# PM2 中以 zhimingge 用户启动
```
---
## 13. 快速命令参考
```bash
# 完整首次部署
cd /opt && git clone https://git.bz121.com/dekun/zhimingge.git zhimingge
cd /opt/zhimingge
cp .env.example .env.local && nano .env.local
pnpm install --frozen-lockfile
pnpm run build
pm2 start ecosystem.config.cjs
pm2 save && pm2 startup
# 日常更新
cd /opt/zhimingge && git pull && pnpm install && pnpm run build && pm2 restart zhimingge
# 查看状态
pm2 status && curl -I http://127.0.0.1:3130
```
---
## 14. 相关文档
- 产品说明:[docs/SPEC.md](./SPEC.md)
- 环境变量示例:[../.env.example](../.env.example)
- PM2 配置:[../ecosystem.config.cjs](../ecosystem.config.cjs)