知微(知识库 Agent)生产部署记录
一个「Vue 前端 + Node 服务 + DeepSeek」的知识库问答应用从零上线:Nginx 反向代理、systemd 守护、Let's Encrypt HTTPS,以及让 SSE 流式回答正常工作的代理配置。
- 部署域名:
https://kb.example.com - 项目仓库:liujw123/knowledge_agent
一、最终架构
Internet
│ HTTPS / 443
▼
Nginx 1.22.1
├─ kb.example.com -> HTTP 301 -> HTTPS
└─ 反向代理 -> 127.0.0.1:3001
│
▼
Node.js 24.12.0
├─ /api/*
├─ frontend/dist
└─ /var/lib/knowledge-agent
- 不依赖 Docker
- 前端静态文件由 Node 服务托管
- SSE 流式回答由 Nginx 反向代理
- 服务由 systemd 守护,异常退出自动重启
- HTTPS 使用 Let's Encrypt + Certbot 自动续期
二、服务器环境
| 组件 | 版本 / 路径 |
|---|---|
| Nginx | 1.22.1 |
| Node.js | v24.12.0 |
| Node 路径 | /usr/local/nvm/versions/node/v24.12.0/bin/node |
| pnpm | 11.24.0 |
| Git | 2.39.5 |
| 域名 | kb.example.com |
| 应用目录 | /opt/knowledge-agent |
| 数据目录 | /var/lib/knowledge-agent |
| 服务用户 | kb |
| Node 服务端口 | 127.0.0.1:3001 |
服务器公网 IP 在文档中省略,配置 DNS 时使用实际服务器 IP。
三、DNS 配置
在阿里云 DNS 添加子域名:
记录类型:A
主机记录:kb
记录值:<服务器公网 IP>
TTL:600
验证:
ping kb.example.com
不直接覆盖
example.com或www.example.com,避免影响现有站点。
四、安装运行环境
sudo apt update
sudo apt install -y git nginx curl
Node.js 已在服务器上通过 NVM 安装:
/usr/local/nvm/versions/node/v24.12.0
安装 pnpm:
npm install -g pnpm@11.24.0
pnpm -v
五、创建运行用户与目录
不要使用 root 直接运行 Node 服务。
sudo useradd --system --create-home --shell /usr/sbin/nologin kb || true
sudo mkdir -p /opt/knowledge-agent /var/lib/knowledge-agent
授权:
sudo chown -R kb:kb /opt/knowledge-agent /var/lib/knowledge-agent
六、拉取代码并构建
cd /opt
sudo -u kb git clone https://github.com/liujw123/knowledge_agent.git knowledge-agent
cd /opt/knowledge-agent
sudo -u kb pnpm install --frozen-lockfile
sudo -u kb pnpm build
构建产物:
frontend/dist
Node 服务启动时会自动托管该目录。
七、配置生产环境变量
sudo -u kb cp /opt/knowledge-agent/server/.env.example /opt/knowledge-agent/server/.env
sudo nano /opt/knowledge-agent/server/.env
生产配置:
PORT=3001
HOST=127.0.0.1
DATA_DIR=/var/lib/knowledge-agent
CORS_ORIGIN=https://kb.example.com
MAX_UPLOAD_MB=100
# 可选:服务端兜底模型
# DEEPSEEK_API_KEY=sk-xxx
DEEPSEEK_BASE_URL=https://api.deepseek.com
DEEPSEEK_MODEL=deepseek-chat
权限:
sudo chown kb:kb /opt/knowledge-agent/server/.env
sudo chmod 600 /opt/knowledge-agent/server/.env
说明:
HOST=127.0.0.1:只允许本机 Nginx 访问,3001 不对公网开放DATA_DIR:文档和知识库状态的持久化目录MAX_UPLOAD_MB:公网部署建议限制上传大小,避免内存被打满DEEPSEEK_API_KEY:可选;如果填写,服务端会保留兜底模型能力
八、systemd 服务
创建:
sudo nano /etc/systemd/system/knowledge-agent.service
内容:
# 服务描述与启动顺序:网络就绪后再启动
[Unit]
Description=Knowledge Agent
After=network.target
# 服务运行参数
[Service]
# simple:ExecStart 进程即为主进程
Type=simple
# 以低权限用户 kb 运行,不使用 root
User=kb
Group=kb
# 工作目录:server 目录,相对路径以此为基准
WorkingDirectory=/opt/knowledge-agent/server
# 生产环境标记
Environment=NODE_ENV=production
# 加载环境变量文件(端口、DATA_DIR、MAX_UPLOAD_MB 等)
EnvironmentFile=/opt/knowledge-agent/server/.env
# 启动命令:使用 NVM 中的 Node 绝对路径 + 后端入口
ExecStart=/usr/local/nvm/versions/node/v24.12.0/bin/node /opt/knowledge-agent/server/src/index.js
# 进程异常退出后自动重启
Restart=always
# 重启前等待 3 秒
RestartSec=3
# 最大打开文件数,避免并发上传/SSE 连接不足
LimitNOFILE=65535
# 安装配置:开机时进入多用户模式即自动启动
[Install]
WantedBy=multi-user.target
启用:
# 重新加载 systemd 配置(修改 .service 文件后必须执行)
sudo systemctl daemon-reload
# 设置开机自启,并立即启动服务
sudo systemctl enable --now knowledge-agent
# 查看服务运行状态(--no-pager 避免进入分页模式)
sudo systemctl status knowledge-agent --no-pager
验证:
curl http://127.0.0.1:3001/api/health
预期:
{
"ok": true,
"model": "deepseek-chat",
"envModelConfigured": true,
"documentCount": 0,
"chunks": 0
}
九、Nginx 反向代理
创建:
sudo nano /etc/nginx/sites-available/kb.example.com
初始 HTTP 配置:
# 虚拟主机:监听 80 端口(HTTP),HTTPS 由 Certbot 后续添加
server {
listen 80;
# IPv6 同样监听 80 端口
listen [::]:80;
# 匹配域名:只有请求头 Host 为该域名时才使用此配置
server_name kb.example.com;
# 允许的最大请求体大小,需与 .env 中 MAX_UPLOAD_MB 保持一致
client_max_body_size 100m;
# 所有路径都转发到后端
location / {
# 反向代理到本机 Node 服务(仅本机可访问)
proxy_pass http://127.0.0.1:3001;
# 使用 HTTP/1.1,保持与后端的长连接
proxy_http_version 1.1;
# 保留原始 Host 头
proxy_set_header Host $host;
# 传递客户端真实 IP
proxy_set_header X-Real-IP $remote_addr;
# 传递代理链 IP 列表
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 告诉后端原始协议(http / https)
proxy_set_header X-Forwarded-Proto $scheme;
# 清空 Connection 头,避免代理断开长连接
proxy_set_header Connection "";
# SSE 流式响应不能缓冲,否则回答会一次性输出
# 关闭响应缓冲
proxy_buffering off;
# 关闭缓存
proxy_cache off;
# 关闭请求体缓冲(上传文件时直接转发)
proxy_request_buffering off;
# 后端读取超时:流式回答较长时不被提前断开
proxy_read_timeout 300s;
# 向后端发送超时
proxy_send_timeout 300s;
}
}
启用:
# 创建软链接,让 Nginx 加载该站点配置
sudo ln -s /etc/nginx/sites-available/kb.example.com /etc/nginx/sites-enabled/
# 检查配置语法是否正确
sudo nginx -t
# 重新加载配置,不中断现有连接
sudo systemctl reload nginx
本机验证:
curl -H "Host: kb.example.com" http://127.0.0.1/api/health
十、HTTPS 配置
现有阿里云免费证书只覆盖:
example.com
www.example.com
不包含 kb.example.com,因此为子域名单独签发 Let's Encrypt 证书:
sudo apt install -y certbot python3-certbot-nginx
sudo certbot --nginx -d kb.example.com
选择自动跳转 HTTPS。
证书位置:
/etc/letsencrypt/live/kb.example.com/fullchain.pem
/etc/letsencrypt/live/kb.example.com/privkey.pem
验证:
curl -I http://kb.example.com
curl -I https://kb.example.com
sudo certbot renew --dry-run
预期:
http -> 301 Location: https://kb.example.com/
https -> 200 OK
可选:添加 HSTS,让浏览器以后优先使用 HTTPS。
在 HTTPS 的 server 块中加入:
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
然后:
sudo nginx -t
sudo systemctl reload nginx
证书类型、SAN、ACME 与 HTTP-01 / DNS-01 的原理,见 HTTPS 证书基础。
十一、页面首次使用
打开:
https://kb.example.com
点击右上角「未配置模型」,填写:
Base URL: https://api.deepseek.com
模型 ID: deepseek-chat
API Key: 你的 DeepSeek Key
点击「测试连接」,成功后「保存并启用」。
然后:
- 打开左侧「知识库」
- 上传 PDF / DOCX / Markdown
- 等待解析和索引完成
- 在聊天框提问
- 点击回答里的引用角标查看原文片段
十二、常见问题与解决
12.1 pnpm: command not found
现象:
sudo -u kb pnpm install --frozen-lockfile
sudo: pnpm: command not found
原因:
Node 和 pnpm 安装在 root 的 NVM 路径:
/usr/local/nvm/versions/node/v24.12.0/bin
kb 用户的 PATH 没有这个目录。
解决:
sudo ln -sf /usr/local/nvm/versions/node/v24.12.0/bin/node /usr/local/bin/node
sudo ln -sf /usr/local/nvm/versions/node/v24.12.0/bin/npm /usr/local/bin/npm
sudo ln -sf /usr/local/nvm/versions/node/v24.12.0/bin/npx /usr/local/bin/npx
sudo ln -sf /usr/local/nvm/versions/node/v24.12.0/bin/pnpm /usr/local/bin/pnpm
验证:
sudo -u kb node -v
sudo -u kb pnpm -v
12.2 systemd 报 203/EXEC
现象:
status=203/EXEC
ExecStart=/usr/bin/node ...
原因:
/usr/bin/node 不存在,Node 实际在 NVM 路径。
解决:
ExecStart=/usr/local/nvm/versions/node/v24.12.0/bin/node /opt/knowledge-agent/server/src/index.js
然后:
sudo systemctl daemon-reload
sudo systemctl restart knowledge-agent
sudo systemctl status knowledge-agent --no-pager
12.3 阿里云免费证书不能复用到子域名
原因:
- 阿里云免费证书是单域名 DV 证书
- 不包含
kb.example.com - 不能给已有证书追加子域名
解决:
- 为
kb.example.com单独申请证书 - 或使用 Let's Encrypt + Certbot
- 多个子域名需要通配符证书
最终使用 Certbot:
sudo certbot --nginx -d kb.example.com
12.4 SSE 流式回答变成一次性输出
原因:
Nginx 默认会缓冲代理响应。
解决:
proxy_buffering off;
proxy_cache off;
proxy_request_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
完整排查顺序与前端解析方式,见 SSE 流式响应。
十三、常用运维命令
# 查看服务状态
sudo systemctl status knowledge-agent --no-pager
# 实时日志
sudo journalctl -u knowledge-agent -f
# 最近 50 行日志
sudo journalctl -u knowledge-agent -n 50 --no-pager
# 重启服务
sudo systemctl restart knowledge-agent
# 检查 Nginx 配置
sudo nginx -t
# 重载 Nginx
sudo systemctl reload nginx
# 查看 Nginx 配置
sudo nginx -T | grep -n "kb.example.com"
# 检查本机 API
curl http://127.0.0.1:3001/api/health
# 检查公网 API
curl https://kb.example.com/api/health
# 检查证书续期
sudo certbot renew --dry-run
十四、更新部署
cd /opt/knowledge-agent
sudo -u kb git pull
sudo -u kb pnpm install --frozen-lockfile
sudo -u kb pnpm build
sudo systemctl restart knowledge-agent
十五、上线检查清单
- [x] DNS 解析
kb.example.com - [x] Node 服务
127.0.0.1:3001 - [x] systemd 守护
- [x] Nginx 反向代理
- [x] HTTP 自动跳转 HTTPS
- [x] Let's Encrypt 证书
- [x] Certbot 自动续期
- [x] 前端页面可访问
- [x] 后端 health 接口正常
- [ ] 页面模型配置
- [ ] 上传文档测试
- [ ] 访问控制 / 服务端 Key 安全处理
速查
# 服务状态 / 实时日志 / 最近 50 行日志
sudo systemctl status knowledge-agent --no-pager
sudo journalctl -u knowledge-agent -f
sudo journalctl -u knowledge-agent -n 50 --no-pager
# 重启服务 / 设置开机自启
sudo systemctl restart knowledge-agent
sudo systemctl enable --now knowledge-agent
# 修改 systemd 配置后重新加载
sudo systemctl daemon-reload
# 检查并重载 Nginx
sudo nginx -t
sudo systemctl reload nginx
# 本机 / 公网健康检查
curl http://127.0.0.1:3001/api/health
curl https://kb.example.com/api/health
# 更新部署:拉代码 → 装依赖 → 构建 → 重启
cd /opt/knowledge-agent
sudo -u kb git pull
sudo -u kb pnpm install --frozen-lockfile
sudo -u kb pnpm build
sudo systemctl restart knowledge-agent
# 检查证书能否自动续期
sudo certbot renew --dry-run
| 场景 | 关键点 |
|---|---|
| 服务起不来 | 先看 systemctl status 与 journalctl -u knowledge-agent -n 50 |
改完 .env / .service 不生效 | 分别执行 daemon-reload、restart |
| 公网 502 | 确认 Node 监听 127.0.0.1:3001,且 Nginx proxy_pass 指向它 |
| 回答一次性输出 | Nginx 关缓冲,详见 SSE 流式响应 |
相关
- HTTPS 证书基础:SAN、DV / OV / EV、ACME、Certbot 与续期
- SSE 流式响应:协议格式、前后端实现与 Nginx 缓冲排查
- 本地构建 + 同步部署到服务器:本站静态站点的发布方式
- 技术笔记总览:全部技术栈入口