☰
开源Wiki本地部署实战:从选型到外部访问的全流程指南
2026/9/29 14:45:49 网站建设 项目流程

数据不落地,心里总觉得不踏实。为了把团队知识库真正攥在自己手里,我对比了一圈开源 wiki 方案,最后选定了 Wiki.js,在一台闲置迷你主机上完成了本地部署,并打通了外部访问的完整链路。整个过程前后花了一个周末,装好之后,手机、平板、公司电脑都能直接打开同一套知识库,体验远比预期的顺滑。

但我不是一上来就拍脑袋决定的。在线文档确实轻量、协作方便,很多场景无可替代。可当我想把项目文档、操作手册、故障记录沉淀成一个可持续维护的知识库时,在线文档的短板就很明显了:数据所有权不在自己手里,权限细粒度受平台限制,内容结构也偏向零散的"一篇篇",缺少 wiki 那种页面互链、树状组织的体系感。所以这次选型和部署,本质上是在回答一个问题:能不能用最小的成本,换来一套完全属于自己的知识库?

这篇文章就是完整的实操复盘,从选型到外部访问再到踩坑排查,都整理成了一份可以直接"抄作业"的笔记。适合正在纠结要不要自建 wiki 的团队技术负责人或独立开发者,也适合手头正好有闲置设备、想搭个人知识库的折腾型玩家。

1. 方案选型:为什么是 Wiki.js

在敲定 Wiki.js 之前,我花了不少时间做对比。很多人会在这一步卡住,因为"开源 wiki"这个关键词一搜,出来的项目一大堆,每个都有自己的拥趸。我实际测过的方案不多,但足够覆盖主流选择:MediaWiki、DokuWiki、Outline,以及最终落地的 Wiki.js。

1.1 主流开源方案横向对比

方案架构语言存储方式编辑器体验权限粒度上手难度我的评价
MediaWikiPHPMySQL/MariaDB老式 wikitext 语法,新人不友好基于账号,配置偏复杂中功能全面,但界面和编辑体验都很"古早"
DokuWikiPHP纯文本文件类 wikitext 语法支持简单 ACL低极轻量,不依赖数据库,但功能上限明显
OutlineNode.jsPostgreSQL + Redis + S3Markdown,界面漂亮基于团队,很灵活中高颜值最高,但依赖组件多,基本只能 Docker 部署
Wiki.jsNode.jsPostgreSQL/MySQL/SQLiteMarkdown,所见即所得支持用户组和精细 ACL中界面现代,生态活跃,本文主角

1.2 Wiki.js 有哪些不可替代的点

第一,它的页面组织方式天生就是"知识库"逻辑。Wiki.js 区分了首页、分类、页面的层级,可以灵活调整导航树结构,页面之间能互相链接、打标签。这一点非常契合知识沉淀的需求。相比之下,很多在线文档工具其实是"目录树下堆文件"的思维,页面之间基本没有语义关联。

第二,数据完全掌握在自己手里。Wiki.js 支持 PostgreSQL、MySQL、MariaDB、SQLite 和 SQL Server 多种数据库,页面内容以 Markdown 形式存储,导出的数据干净、可迁移。我可以把数据库文件定时备份到另一台设备,也可以直接把附件从磁盘拷走,不用担心被平台限制。

第三,权限管理足够细。可以为用户组设置查看、编辑、评论、管理权限,甚至可以细化到单页面、单分类。对"给外部顾问开个只读入口"或者"只允许某位同事编辑某几个模块"这类需求来说,操作起来很顺手。

第四,部署成本不算高。官方提供针对 Linux、Windows、macOS 的安装包,也提供 Docker 镜像。单机模式用 SQLite 就能跑起来,对一台 2GB 内存的小主机来说压力不大;真到了团队规模,升级到 PostgreSQL 也只是改一个连接串的事。

补充一句:Wiki.js 提供了官方直出的安装包,不需要像某些项目那样必须依赖 Docker 全家桶。这对不熟悉容器技术、或者设备配置一般的人来说,友好程度高很多。

2. 本地部署前的环境准备

2.1 硬件与系统版本

我用的是一台退役的迷你主机,CPU 是 Intel J4125,内存 8GB,硬盘 120GB SATA SSD。系统刷的是 Debian 12 精简安装版,没有桌面环境。这个配置对 Wiki.js 来说相当宽裕——官方建议的最低配置是 512MB 内存加 1GHz 双核 CPU,实际跑起来,一个 Node.js 进程加上 PostgreSQL,内存占用大概也就 400MB 上下。

如果你手头只有树莓派 3B+、玩客云这类设备,也可以尝试 SQLite 模式,把内存占用压到最低。但如果你计划给多人使用,或者页面数量会超过几千篇,推荐直接上 PostgreSQL,读写性能和并发支持会稳妥很多。

2.2 数据库选型:PostgreSQL 还是 SQLite

这其实是个很实际的问题。我的判断标准很简单:

  • 单用户、个人自用、页面量小:SQLite 完全够用,零配置,装完就能跑。
  • 多用户、团队协作、需要权限控制:PostgreSQL 是最稳妥的选择。

我选了 PostgreSQL。原因有两个:一是 Wiki.js 的权限机制在 PostgreSQL 下表现最完整;二是我这台机器还跑了别的服务,PostgreSQL 可以顺便给其他项目用,一套数据库实例不浪费。

安装 PostgreSQL 的命令,Debian/Ubuntu 通用:

sudo apt update sudo apt install postgresql postgresql-contrib -y

然后创建数据库和专用账号:

sudo -u postgres psql CREATE USER wikijs WITH PASSWORD '请换成强密码'; CREATE DATABASE wiki; GRANT ALL PRIVILEGES ON DATABASE wiki TO wikijs; \q

这里有三个细节值得留意,都是我实际踩过的:

  • 不要用系统默认的postgres超级用户去连应用,务必单独建一个低权限账号。这样数据库与应用账号分离,后面出问题时容易定位。
  • 如果 Wiki.js 和 PostgreSQL 跑在同一台机器上,连接串用127.0.0.1就行,没必要监听外网。检查一下pg_hba.conf,确认默认规则没有被改坏。
  • 如果密码里有特殊字符,记得在连接串里做 URL 编码,否则会像我第一次配置时那样,卡在"数据库连接失败"上,排查了很久才发现是密码解析的问题。

2.3 Node.js 环境安装

Wiki.js 的运行时是 Node.js,官方支持 Node 18 和 Node 20。系统自带的 Node 版本往往比较老,推荐直接从 NodeSource 仓库装:

curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash - sudo apt install nodejs -y node -v npm -v

实测下来,在 Debian 12 上用 NodeSource 装 Node 18 是最省事的路子。如果你打算用 Docker 方式部署,那 Node 环境就不用管了,官方镜像里已经打包好了。

3. Wiki.js 安装与首次初始化

3.1 下载并解压安装包

Wiki.js 的安装包可以从官方 release 页面下载。以当前稳定版为例:

cd /opt sudo wget https://github.com/requarks/wiki/releases/download/2.5.303/wiki-js.tar.gz sudo mkdir -p /opt/wiki sudo tar -xzf wiki-js.tar.gz -C /opt/wiki cd /opt/wiki sudo cp config.sample.yml config.yml

config.yml是 Wiki.js 的核心配置文件,服务启动时会读取它。我建议先只改数据库连接部分,其他参数保持默认,等初始化完成后再根据实际情况精调。

3.2 配置文件修改

打开config.yml,找到db段落,改成下面这样:

db: type: postgres host: 127.0.0.1 port: 5432 user: wikijs pass: '你的强密码' db: wiki

这里有个细节:YAML 中密码如果以@、%这类特殊字符开头,一定要用单引号包起来,否则解析器会直接拆错字符串。我第一次就是踩了这个坑,密码里含@却裸写,结果服务一直报连接失败。

3.3 注册为系统服务

推荐用 systemd 管理 Wiki.js 进程。把下面的内容保存到/etc/systemd/system/wiki.service:

[Unit] Description=Wiki.js After=network.target [Service] Type=simple ExecStart=/usr/bin/node /opt/wiki/server/server.js Restart=always User=www-data Environment=NODE_ENV=production WorkingDirectory=/opt/wiki [Install] WantedBy=multi-user.target

然后启动:

sudo systemctl daemon-reload sudo systemctl enable --now wiki sudo systemctl status wiki

这个环节有三个常见问题:

  • 如果/opt/wiki里的文件属主不是www-data,node 进程可能没有写权限。遇到过一种症状:页面能打开,但附件传不上来。用sudo chown -R www-data:www-data /opt/wiki解决。
  • Wiki.js 默认监听 3000 端口。如果本机 3000 被其他服务占用,启动会失败,排查时先ss -lntp看端口占用。
  • 启动失败十有八九是 YAML 配置文件的缩进问题。config.yml对空格非常敏感,用cat -A config.yml能看到行尾隐藏字符,帮忙定位哪里写歪了。

3.4 浏览器初始化向导

服务启动后,浏览器访问http://服务器IP:3000,会进入安装向导。流程很短:

  1. 进入语言选择界面。注意,安装向导的语言和后续管理界面的语言是分开设置的,这里先选英文也没关系,管理员后台里可以再切换。
  2. 填写管理员邮箱和密码。这个邮箱后面就是登录名。
  3. 完成后进入欢迎页,系统会引导你创建第一个页面。

初始化完成后,Wiki.js 的界面很直观:左侧是导航树,中间是内容区,右上角是搜索框。首次打开后台后,会自动出现"创建首页"的提示,点击就能进入 Markdown 编辑器。整个编辑体验和现代 Markdown 编辑器很像,代码高亮、表格、引用块都支持,团队成员上手基本没有学习成本。

我额外做的两件事:一是在系统设置里把站点语言改成中文;二是调整了导航栏结构,把"团队规范""项目文档""运维手册"三个分类先建好。这个动作看起来不起眼,但对后续的使用帮助很大——分类结构提前想清楚,比页面堆到几百篇之后再迁移强得多。

4. 外部访问:让知识库走出局域网

本地部署完成后,wiki 只能在局域网里用,这充其量是个半成品。要让外部设备访问,有几条路径,先评估自己的网络环境再选。

4.1 先搞清楚你的网络条件

动手之前,先回答两个问题:你的宽带有公网 IPv4 吗?你家有能用的 IPv6 吗?

判断方法很简单:把家中路由器的 WAN 口 IP,和在公网 IP 查询网站上查到的出口 IP 对比一下。一致说明你有公网 IPv4;不一致说明你处于运营商 NAT 之后,传统的端口映射方案就不好用了。另外,可以找支持 IPv6 的测试网站确认一下本机的 IPv6 连通性。

我自己是电信宽带,IPv4 被运营商 NAT,但 IPv6 可用。所以我的外部访问方案是:在路由器上放行 IPv6 防火墙端口,配合 DDNS 动态解析指向路由器的 IPv6 地址,这样外部设备就能通过域名访问。

4.2 端口映射和 DDNS

端口映射是最经典的外部访问方式:路由器把公网入口的某个端口,转发到内网服务器的 3000 端口。配置一般位于路由器后台的"端口映射"或"虚拟服务器"菜单,不同品牌界面不一样,但核心字段都是这几个:

  • 公网端口:不建议直接用 3000,我改成了 8443,减少被扫描器盯上的概率。
  • 内网地址:填 wiki 主机的局域网 IP,比如 192.168.1.100。
  • 内网端口:3000。
  • 协议:TCP。

公网 IP 是会变化的,所以最好配一个 DDNS 服务,把动态 IP 映射到固定域名。现在的家用路由器基本都自带 DDNS 功能,注册一个免费动态域名,填进去即可。

4.3 没有公网 IPv4 的替代方案

如果公网 IPv4 被 NAT,但有 IPv6,走 IPv6 是成本最低的方案。主要做两件事:

  1. 在路由器安全设置中放行 TCP 端口 8443,指向 wiki 服务器的 IPv6 地址。
  2. 设置 DDNS,把域名解析到本机 IPv6 地址,并确保记录类型是 AAAA。

需要注意,IPv6 地址很长,部分老设备对 IPv6 支持不好,访问时可能会失败。

如果连 IPv6 都没有,那更省心的方案是用组网工具,比如 Tailscale、ZeroTier 这一类。这类工具会在两台设备之间建立一个加密的虚拟局域网,让外部设备看起来就像在同一个局域网里一样。我在随身笔记本上装了 Tailscale,登录同一个账号后,直接访问http://wiki主机在Tailscale里的IP:3000,不需要做任何端口映射,体验非常接近局域网访问。

提示:组网工具的实质是构建虚拟局域网,作为远程访问自家设备的效率工具来用,是常规且合规的技术方案,别想歪了。

4.4 加一层反向代理,让 HTTPS 和域名更优雅

直接对外暴露 3000 端口,能用,但不推荐。原因有三:

  • Node.js 自带的 HTTP 服务在并发压力较大时表现一般,前面挂一层 Nginx 或 Caddy 可以做缓冲。
  • 没有域名和 HTTPS,访问体验不好,也有被中间人监听的风险。
  • 应用端口直接暴露在公网上,容易被扫描器扫到并试探漏洞。

我选择用 Caddy 做反向代理,配置真的是极简。安装 Caddy 后,在Caddyfile里写几行:

wiki.example.com { reverse_proxy 127.0.0.1:3000 }

Caddy 会自动申请并续期 Let's Encrypt 证书,把 HTTPS 一起搞定。前提是你把域名解析到了你的公网 IP(或 IPv6 地址)。

如果你更习惯 Nginx,配置也不复杂:

server { listen 443 ssl; server_name wiki.example.com; ssl_certificate /path/to/cert.crt; ssl_certificate_key /path/to/cert.key; location / { proxy_pass http://127.0.0.1:3000; 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_set_header Host $host这一行一定不能省。Wiki.js 在生成内部链接和 OAuth 回调地址时,依赖 Host 头来拼接完整 URL。如果配置里漏掉它,很可能会出现登录成功后被跳回http://127.0.0.1:3000的诡异情况,而且后台的某些绝对链接也会指向错误地址。

4.5 开放外网后的安全加固清单

外网访问打通之后,安全必须跟上。我给自己列了四个必做项:

  • 强制 HTTPS。用 Caddy 是自动的;手动 Nginx 的话,记得把 80 端口统一跳转到 443。
  • 不要用默认端口。前面已经通过反向代理把入口收敛到 443/80,内网 3000 端口不作为对外入口。
  • 防火墙收敛端口。Debian 上我用 nftables 写的规则,也可以用 ufw,通过sudo ufw allow 443/tcp这类命令快速放行。注意只放行必要端口。
  • 配置自动备份。外网访问意味着风险,一旦数据被误删或篡改,能依赖的只有备份。我开始没配备份,后来写了脚本每天把 PostgreSQL 数据库 dump 一次,再 rsync 到另一台机器。这个习惯强烈建议一开始就养成。

4.6 首次外网访问验收清单

配置完之后,我按这个顺序逐项验证:

  1. 关闭家中的 Wi-Fi,用手机流量访问https://wiki.example.com,确认能打开。
  2. 登录后台,创建一个仅自己可见的测试页面,发布并访问,确认权限和路由都正常。
  3. 换一台外部设备,用同一个域名再访问一次,排除本地缓存或 DNS 环境因素。
  4. 查看 Wiki.js 后台日志,确认没有异常报错。

这一套走下来,外部访问链路才算真正闭环。

5. 常见问题与排查技巧实录

5.1 启动即失败,进程根本起不来

这类问题占了我调试时间的一半,典型表现是systemctl status wiki显示Active: failed。

优先排查三件事:

  • 端口占用。ss -lntp | grep 3000看 3000 端口是否被别的服务先占了,占用的话改 Wiki.js 的config.yml里的port参数。
  • 配置格式。node -c config.yml能检查 YAML 语法,但更有效的还是cat -A config.yml看有没有混入 Tab 制表符或行尾多余空白。
  • 权限。确保/opt/wiki目录属主是www-data,数据库用户也用的是普通账号而不是超级用户。

5.2 数据库连接失败,密码没问题

如果确认数据库密码和 user 都是对的,连接还是失败,最常见的原因就是特殊字符没转义。连接串或 YAML 里的密码,建议统一用单引号包住。用户里包含@时,在 Postgres 连接串里要写成%40。这个坑非常隐蔽,日志里报的错也可能只是模糊的"connection failed"。

5.3 外网访问不通,但局域网正常

局域网能访问,说明 Wiki.js 本身没问题,问题一定出在网络链路。按顺序排查:

  • 先确认有没有公网 IPv4。用 4.1 说的办法,看路由器 WAN 地址和公网查询结果是否一致。
  • 看 4.2 的端口映射是否生效。有些路由器改完设置要重启,另外确认内网 IP 有没有写错。
  • 如果是 IPv6 方案,检查电脑上ping6域名通不通,不通就是 DNS 的 AAAA 记录或路由器防火墙放行有问题。
  • 如果是组网工具,先确认外部设备在虚拟局域网里能不能 ping 通 wiki 主机。

5.4 登录后跳回 127.0.0.1

这个场景基本锁定在反向代理配置上。Wiki.js 通过请求里的 Host 头判断当前站点地址来做跳转。我在 Nginx 配置里漏掉proxy_set_header Host $host就复现过,加上之后问题消失。Caddy 的reverse_proxy会自动带上 Host 头,所以在 Caddy 下很少遇到这个问题。

5.5 附件无法上传,页面却一切正常

页面能看、能写,但图片和文件传不上去,大概率是文件系统权限问题。检查/opt/wiki/data目录是否对 node 进程运行用户可写。我那次就是chown -R www-data:www-data /opt/wiki之后就好了。

我一直觉得,排查技术问题时,带着"怀疑自己而不是怀疑别人"的心态会高效很多。Wiki.js 本身是个很成熟的项目,绝大多数异常都不是它的 bug,而是环境配置、权限、端口这些周边环节出了偏差。按着"启动失败→数据库不通→页面异常→外网不通"这个顺序逐层排查,基本都能定位到根因。

6. 一些使用心得和后续扩展方向

如果用一句话总结这次部署,就是:Wiki.js 的难度不在于装,而在于给它一个合理的定位和结构。安装过程两小时就能跑通,但真正让它变成团队可靠的"第二大脑",靠的是日常维护——目录结构、权限划分、备份策略,这些事比部署本身更费心。

我在使用了三周之后,重新调整了 wiki 的目录结构,把原来按日期堆页面改成了按项目划分。这个看似简单的动作,比部署本身花的精力多得多。所以如果你也准备动手,我的建议是:先把分类想清楚再建站。Wiki.js 的树状导航和多级权一旦搭好,后面迁移会轻松很多。

最后分享一个小技巧:Wiki.js 内置了 GraphQL API,可以编程创建页面、批量导入导出内容。我后来写了一个小脚本,每周自动把 Git 仓库的 commit 记录整理成一份变更日志页面,相当于让 wiki 承担了一部分自动化周报的活。这个思路可以继续扩展,比如把 CI 构建结果、监控告警事件都通过 API 推送到 wiki 上,让知识库真的动起来,而不是像传统文档一样装完就沉睡。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询