Files
dekun a1667eac51 Add Docker deployment as the recommended production setup.
Include Dockerfile, docker-compose on port 3130, npm mirror config, deploy scripts, and DOCKER.md; keep PM2 docs as fallback.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-10 21:13:12 +08:00

493 lines
11 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.
# 知命阁(zhiminggeUbuntu 部署文档(PM2 备选)
> 仓库:[https://git.bz121.com/dekun/zhimingge.git](https://git.bz121.com/dekun/zhimingge.git)
> **推荐改用 Docker 部署**,见 [DOCKER.md](./DOCKER.md)。本文档保留 PM2 手动部署说明。
本文档说明在 **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 安装 PM2
```bash
npm install -g pm2
pm2 -v
```
> **说明**:项目使用 **npm** + `package-lock.json` 安装依赖(无需 pnpm)。若已安装 pnpm 也可改用 `npm install`,避免 `pnpm-lock.yaml` 不同步问题。
### 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
npm ci || npm install
```
### 7.2 生产构建
```bash
npm 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` 使用项目根目录 + `npm 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
# 安装新依赖(如有变更)
npm ci || npm install
# 重新构建
npm 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 |
| `npm install` 长时间无输出 | 官方 npm 源慢 / 下载 `@next/swc` 等大包 | 见下方「npm 安装卡住」 |
### npm 安装卡住
国内服务器访问 `registry.npmjs.org` 常极慢,表现为 `npm install` 只有转圈、无进度。
**1. 先 Ctrl+C 中断,改用国内镜像:**
```bash
cd /opt/zhimingge
npm config set registry https://registry.npmmirror.com
npm config set fetch-timeout 600000
npm install --no-audit --no-fund --loglevel=info
```
项目根目录已包含 `.npmrc``git pull` 后自动生效),也可直接:
```bash
git pull origin main
npm install --loglevel=info
```
**2. 看卡在哪一步**(可选):
```bash
npm install --loglevel=verbose 2>&1 | tee /tmp/npm-install.log
```
若长时间停在 `@next/swc-*``sharp`,属正常现象,多等几分钟;超 10 分钟仍无进展再换镜像重试。
**3. 内存不足时**(构建阶段 OOM)见下方 Swap 配置。
### 构建内存不足时增加 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``npm 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
npm ci || npm install
npm run build
pm2 start ecosystem.config.cjs
pm2 save && pm2 startup
# 日常更新
cd /opt/zhimingge && git pull && npm ci && npm 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)