VanBlog 源码搭建与前后端分离部署指南
2026-07-21
安装搭建
00

目录

一、项目结构(源码)
二、环境准备
三、从源码构建
1. 后端 Server
2. 管理后台 Admin
3. 前台 Website
四、推荐的拆分部署方式
拓扑示意
公网 Nginx(前台)示意
内网 Nginx(后台)示意
五、systemd 守护(示例)
六、初始化与登录
七、常见问题
1. /api/admin/meta 返回 401
2. 登录提示密码错误
3. 前台发文后看不到更新
4. 忘记管理员密码
八、参考链接

VanBlog 是一款开源的个人博客系统(GPL-3.0),仓库地址:

https://github.com/mereithhh/van-blog

官方提供 Docker / 一键脚本部署。本文记录的是 从 GitHub 源码本地构建,并拆分前后端部署 的完整流程,适合需要前后端分离、内网托管管理后台的场景。

本站当前架构大致如下:

角色说明
前台 WebsiteNext.js 静态站,对外提供访客页面
后端 ServerNestJS API + MongoDB + Waline 评论
后台 AdminUmi 管理面板,建议仅内网访问
隧道内网后端通过 SSH 反向隧道把 API 暴露给公网前台

一、项目结构(源码)

克隆仓库后,核心在 packages/

text
vanblog/ ├── packages/ │ ├── server/ # NestJS 后端(默认 :3000) │ ├── website/ # Next.js 前台(默认 :3001) │ ├── admin/ # 管理后台(构建为静态资源) │ ├── waline/ # 评论服务(由 server 拉起) │ └── cli/ ├── docs/ └── package.json # pnpm monorepo

运行关系可以简化为:

text
浏览器 ──► Website(:3001) ── /api ──► Server(:3000) ──► MongoDB 浏览器 ──► Admin(静态) ── /api ──► Server(:3000) Server ──► Waline(:8360)

二、环境准备

建议环境:

  • Node.js 18 LTS
  • pnpm(仓库自带 pnpm-lock.yaml
  • MongoDB 4.4+ / 5.x / 6.x
  • Nginx(反代静态与 API)
  • (可选)autossh / systemd,用于隧道与进程守护
bash
# 示例:启用 pnpm corepack enable corepack prepare pnpm@8 --activate git clone https://github.com/mereithhh/van-blog.git cd van-blog pnpm install

构建时若遇到 OpenSSL / 内存问题,可设置:

export NODE_OPTIONS='--max_old_space_size=4096 --openssl-legacy-provider'


三、从源码构建

1. 后端 Server

bash
pnpm --filter server build # 产物:packages/server/dist

生产启动示例环境变量:

bash
export NODE_ENV=production export VAN_BLOG_DATABASE_URL='mongodb://127.0.0.1:27017/vanBlog?authSource=admin' export VAN_BLOG_STATIC_PATH=/opt/vanblog/data/static export VAN_BLOG_LOG=/opt/vanblog/log # 前后端分离、本机不跑 website 时: export VANBLOG_DISABLE_WEBSITE=true node packages/server/dist/src/main.js

Server 默认监听 3000,并会按配置拉起 Waline(默认 8360)。

2. 管理后台 Admin

Admin 以子路径 /admin/ 部署时,需要生产构建:

bash
export EEE=production pnpm build:admin # 产物:packages/admin/dist # base / publicPath 均为 /admin/

用 Nginx 托管 dist,并把 /api/static 反代到 Server。

3. 前台 Website

bash
pnpm --filter website build # 使用 standalone 产物更利于部署

前台需要能访问到后端 API,例如:

bash
export VAN_BLOG_SERVER_URL=http://127.0.0.1:3000 export PORT=3001 node packages/website/server.js # standalone 路径以实际产物为准

四、推荐的拆分部署方式

拓扑示意

text
公网机器 A(前台) 内网机器 B(后端 + 后台) ┌─────────────────────┐ ┌──────────────────────────┐ │ Nginx :80 │ │ Nginx :80 → Admin 静态 │ │ Website :3001 │◄─SSH隧道─│ Server :3000 │ │ 反代 /api → :3000 │ │ MongoDB │ └─────────────────────┘ │ Waline :8360 │ └──────────────────────────┘

要点:

  1. 前台放公网:只暴露 Website + 必要的 /api/static
  2. 后台放内网:Admin 不要映射到公网,降低爆破风险。
  3. SSH 反向隧道:由内网机器主动连公网,把本机 3000/8360 映射到公网机的 127.0.0.1:3000/8360,供前台 Nginx / Website 访问。
  4. 隧道建议做成 systemd 服务,并可用 timer 在每天凌晨做一次重连保活。

公网 Nginx(前台)示意

nginx
server { listen 80; server_name your.domain; location / { proxy_pass http://127.0.0.1:3001; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location /api/ { proxy_pass http://127.0.0.1:3000/api/; client_max_body_size 50m; } location /static/ { proxy_pass http://127.0.0.1:3000/static/; } # 不建议对公网开放 /admin }

内网 Nginx(后台)示意

nginx
server { listen 80; root /var/www; location = / { return 302 /admin/; } location /admin/ { try_files $uri $uri/ /admin/index.html; } location /api/ { proxy_pass http://127.0.0.1:3000/api/; client_max_body_size 50m; } location /static/ { proxy_pass http://127.0.0.1:3000/static/; } }

packages/admin/dist 软链到 /var/www/admin 即可。


五、systemd 守护(示例)

MongoDB / Server / Website / 隧道 都可以写成 service。Server 示例:

ini
[Unit] Description=VanBlog NestJS API Server After=network.target [Service] Type=simple WorkingDirectory=/opt/vanblog/packages/server Environment=NODE_ENV=production Environment=VANBLOG_DISABLE_WEBSITE=true Environment=VAN_BLOG_DATABASE_URL=mongodb://127.0.0.1:27017/vanBlog?authSource=admin Environment=VAN_BLOG_STATIC_PATH=/opt/vanblog/data/static Environment=VAN_BLOG_LOG=/opt/vanblog/log ExecStart=/usr/local/bin/node dist/src/main.js Restart=always [Install] WantedBy=multi-user.target

隧道(示意,按实际用户与端口调整):

bash
autossh -M 0 -N \ -o ServerAliveInterval=30 -o ServerAliveCountMax=3 \ -R 3000:127.0.0.1:3000 \ -R 8360:127.0.0.1:8360 \ user@公网机器

六、初始化与登录

  1. 浏览器访问内网 Admin:http://<内网IP>/admin/
  2. 首次未初始化时,会进入初始化向导(创建管理员、站点信息)
  3. 初始化完成后,用管理员账号登录后台发文、改站点设置

站点「网站 URL」请填写完整协议,例如:https://www.example.com,否则 RSS、部分跳转可能异常。

图床本地模式下,图片一般落在 VAN_BLOG_STATIC_PATH,通过 /static/img/... 访问;前后端分离时请保证公网也能反代到 /static


七、常见问题

1. /api/admin/meta 返回 401

站点已初始化后,该接口需要登录。未登录时返回 401 是正常现象,后台会跳到登录页。带上有效 token 请求头后应返回 200。

2. 登录提示密码错误

VanBlog 密码不是明文传输:

  1. 前端先用 encryptPwd(username, password) 做浏览器侧哈希
  2. 后端再用盐 encryptPassword(username, hash, salt) 校验

因此用接口调试时,不能直接把明文密码塞进 password 字段。

3. 前台发文后看不到更新

拆分部署且 VANBLOG_DISABLE_WEBSITE=true 时,Server 不会自动触发本机 ISR。需要:

  • 给 Website 配置可达的 API,并依赖 ISR / revalidate 时间;或
  • 手动请求前台:/api/revalidate?path=/(以及文章、分类等路径)

4. 忘记管理员密码

Server 启动日志会打印恢复密钥;也可写入日志目录下的 restore.key。在后台「忘记密码」页用该密钥重置。


八、参考链接


以上即为本站采用的 VanBlog 源码搭建与拆分部署流程,后续文章会继续补充运维与使用笔记。

ai协作,人工编辑

本文作者:张老板

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!