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>
11 KiB
知命阁(zhimingge)Ubuntu 部署文档(PM2 备选)
推荐改用 Docker 部署,见 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 更新系统
apt update && apt upgrade -y
3.2 安装 Node.js 20(推荐 LTS)
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs
node -v # 应 >= v20
npm -v
3.3 安装 PM2
npm install -g pm2
pm2 -v
说明:项目使用 npm +
package-lock.json安装依赖(无需 pnpm)。若已安装 pnpm 也可改用npm install,避免pnpm-lock.yaml不同步问题。
3.4 安装 Git
apt install -y git
3.5(可选)安装 Nginx 反向代理
若需域名 + HTTPS,建议安装 Nginx 与 Certbot:
apt install -y nginx certbot python3-certbot-nginx
4. 克隆与目录
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 为私有仓库,克隆前需配置认证。
方式 A:HTTPS + 访问令牌(推荐)
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 权限)。
方式 B:SSH
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. 环境变量
cd /opt/zhimingge
cp .env.example .env.local
nano .env.local
.env.local 示例:
# 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
保存后限制权限:
chmod 600 .env.local
7. 构建与启动
7.1 安装依赖
cd /opt/zhimingge
npm ci || npm install
7.2 生产构建
npm run build
构建成功后生成 .next/standalone/ 独立运行包。
7.3 复制静态资源(standalone 必需)
Next.js standalone 模式需手动链接静态文件:
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:
cd /opt/zhimingge
pm2 start ecosystem.config.cjs
pm2 save
pm2 startup
# 按 PM2 提示执行生成的命令,确保开机自启
常用 PM2 命令:
pm2 status # 查看状态
pm2 logs zhimingge # 查看日志
pm2 restart zhimingge # 重启
pm2 stop zhimingge # 停止
pm2 delete zhimingge # 删除进程
7.5 备选:standalone 直接运行
若希望仅运行 standalone 产物(体积更小):
cd /opt/zhimingge/.next/standalone
PORT=3130 node server.js
对应 PM2 配置片段:
{
name: "zhimingge",
cwd: "/opt/zhimingge/.next/standalone",
script: "server.js",
env: {
PORT: 3130,
NODE_ENV: "production",
},
}
此时需确保 content/、public/ 路径在代码中相对于 cwd 可访问。
7.6 验证
curl -I http://127.0.0.1:3130
# 应返回 HTTP/1.1 200
浏览器访问:http://服务器IP:3130
8. Nginx 反向代理(可选)
假设域名为 zhimingge.example.com:
nano /etc/nginx/sites-available/zhimingge
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;
}
}
ln -s /etc/nginx/sites-available/zhimingge /etc/nginx/sites-enabled/
nginx -t
systemctl reload nginx
# HTTPS(Let's Encrypt)
certbot --nginx -d zhimingge.example.com
9. 更新部署流程
代码推送至 Gitea 后,在服务器执行:
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:
# 仅 Nginx 对外(推荐)
ufw allow 22
ufw allow 80
ufw allow 443
ufw enable
# 若不用 Nginx,直接暴露 3130
ufw allow 3130
11. 日志与排错
PM2 日志
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 中断,改用国内镜像:
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 后自动生效),也可直接:
git pull origin main
npm install --loglevel=info
2. 看卡在哪一步(可选):
npm install --loglevel=verbose 2>&1 | tee /tmp/npm-install.log
若长时间停在 @next/swc-* 或 sharp,属正常现象,多等几分钟;超 10 分钟仍无进展再换镜像重试。
3. 内存不足时(构建阶段 OOM)见下方 Swap 配置。
构建内存不足时增加 Swap
fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
测试 AI 接口
curl https://op.bz121.com/v1/models \
-H "Authorization: Bearer 你的OPENAI_API_KEY"
确认返回列表中包含 huihui_ai/gemma-4-abliterated:e4b。
12. 安全建议
虽然当前按 root 部署,仍建议:
.env.local权限 设为600,勿提交 Git- API Key 仅保存在服务器,不要写入前端代码
- 生产环境使用 Nginx + HTTPS
- 定期
apt update与npm update - 若后续改为非 root 运行,创建专用用户:
useradd -r -s /bin/false zhimingge
chown -R zhimingge:zhimingge /opt/zhimingge
# PM2 中以 zhimingge 用户启动
13. 快速命令参考
# 完整首次部署
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
- 环境变量示例:../.env.example
- PM2 配置:../ecosystem.config.cjs