WikiDocs 2.0 配置参数详解
目标:讲清 WikiDocs(Wiki|Docs)2.0.2 的两层参数体系——进程级环境变量(MODE/SECRET/PORT/DATASETS/FRONTEND)与站点级 settings.json(9 字段)及 accounts.json、pinned.json 数据文件,逐项给出约束、默认值、修改方式与实测校验回显,并实测沉淀 SECRET 轮换导致全员登录失败等 5 个高频配置故障的处理
WikiDocs 2.0 配置参数详解
目标:讲清 WikiDocs(Wiki|Docs)2.0.2 的两层参数体系——进程级环境变量(MODE/SECRET/PORT/DATASETS/FRONTEND)与站点级 settings.json(9 字段)及 accounts.json、pinned.json 数据文件,逐项给出约束、默认值、修改方式与实测校验回显,并实测沉淀 SECRET 轮换导致全员登录失败等 5 个高频配置故障的处理方案。已在 Ubuntu 26.04.1 LTS + WikiDocs 2.0.2 环境逐条实测通过。
一、环境信息
本文所有命令与回显均在以下真实环境逐条实测,读者在相近环境可按原文复现。
- 操作系统:Ubuntu 26.04.1 LTS(内核 7.0.0-38-generic)
- 应用版本:WikiDocs 2.0.2(官方镜像
zavy86/wikidocs:2,后端运行时 Node.js v22.23.4) - 部署形态:按 《WikiDocs 2.0 Docker Compose 部署指南》第四章完成的单实例部署
- 服务端口:宿主机 8132 → 服务内 3210
- 数据目录:
/opt/wikidocs/datasets(挂载到服务内/var/lib/wikidocs/datasets) - 演示账号:管理员
admin@lab.local/q1w2e3r4(另含一个author@lab.local演示作者号) - 参数取证口径:运行实例实测(curl 回显)+ 2.0.2 官方源码(
backend/src/services/environment.service.ts、backend/src/schemas/settings.schema.ts、backend/src/services/accounts.service.ts)
二、前置条件
-
已按部署指南完成 WikiDocs 2.0.2 部署并完成初始化(存在管理员账号)。部署与环境变量注入方式见 《WikiDocs 2.0 Docker Compose 部署指南》第四、六章。
-
健康检查通过(后续所有实测都在该状态下进行):
curl -s -o /dev/null -w 'GET /api/health -> %{http_code}\n' http://127.0.0.1:8132/api/health
GET /api/health -> 204
- 准备一个管理员访问令牌(有效期 900 秒,过期重新获取即可):
curl -s -X POST http://127.0.0.1:8132/api/authenticate \
-H 'Content-Type: application/json' \
-d '{"account":"admin@lab.local","password":"q1w2e3r4"}'
输出节选(实测首尾):
{"jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkdXJhdGlvbiI6OTAwLCJnZW5lcmF0aW9uIjoiMjAyNi0xMC0zMFQwNjo1MTowOC40MTZaIiwiZXhwaXJhdGlvbiI6IjIwMjYtMTAtMzBUMDc6MDY6MDguNDE2WiIsImFjY291bnQiOiJhZG1pbkBsYWIubG9jYWwiLCJyb2xlIjoiYWRtaW5pc3RyYXRvciIsImF1dGhvcml6YXRpb25zIjpbInJlYWQiLCJ3cml0ZSIsImRlbGV0ZSIsInN5bmMiLCJtYW5hZ2UiXSwiaWF0IjoxNzkzMzQzMDY4fQ.rDzLBd…"}
JWT=$(curl -s -X POST http://127.0.0.1:8132/api/authenticate \
-H 'Content-Type: application/json' \
-d '{"account":"admin@lab.local","password":"q1w2e3r4"}' \
| sed 's/.*"jwt":"\([^"]*\)".*/\1/')
echo "$JWT" | head -c 40; echo ' # 后文统一用 $JWT 指代该令牌'
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkdXJhdGlvbiI6OTAwLCJnZW5lcmF0aW9u # 后文统一用 $JWT 指代该令牌
三、参数查看与修改方式
WikiDocs 2.0 的参数分两层,修改入口与生效方式完全不同,先分清再动手:
- 进程级环境变量(MODE、SECRET、PORT、DATASETS、FRONTEND):服务启动时读取一次,运行期不可通过接口修改,改完必须重建服务进程才生效;
- 站点级数据文件(settings.json、accounts.json、pinned.json):存放在数据集目录,服务对它们按请求实时读盘,既可以通过 REST 接口改,也可以直接编辑文件,改完立即生效、无需重启。
3.1 环境变量的查看方式
部署时注入的环境变量以进程配置为准,直接查运行实例:
docker inspect wikidocs-2.0.2-web --format '{{range .Config.Env}}{{println .}}{{end}}' \
| grep -vE '^(PATH|NODE_VERSION|YARN_VERSION|NODE_ENV)='
MODE=public
SECRET=q1w2e3r4-instance-secret-key
PORT=3210
FRONTEND=/app/frontend
DATASETS=/var/lib/wikidocs/datasets
💡 说明:
grep -vE过滤掉的是 Node.js 基础镜像自带变量,与 WikiDocs 无关。MODE、SECRET、PORT、DATASETS、FRONTEND这 5 个就是应用读取的全部业务环境变量(与源码environment.service.ts的 getMode/getSecret/getDatasetsRoot 一一对应),其中FRONTEND指向前端静态资源目录、镜像内已固定,实际需要运维关注的只有前 4 个。
3.2 settings.json 的两种修改入口
入口一:REST 接口。读取接口 GET /api/settings 匿名即可访问(实测未带令牌返回 200 与完整配置);写入接口 PUT /api/settings 必须携带令牌:
curl -s -w '\nHTTP %{http_code}\n' http://127.0.0.1:8132/api/settings
{"title":"Lab Wiki","subtitle":"实验知识库","owner":"Admin User","notice":"Copyright © 2026 Admin","privacy":null,"localization":"zh","timezone":"Asia/Shanghai","template":"dark","color":"#1e88e5"}
HTTP 200
curl -s -w '\nHTTP %{http_code}\n' -X PUT http://127.0.0.1:8132/api/settings \
-H 'Content-Type: application/json' -d '{"title":"T"}'
{"message":"You must provide an authentication token..","error":"Unauthorized","statusCode":401}
HTTP 401
带令牌整体提交 9 个字段(PUT 是全量覆盖语义,漏掉的字段会被校验拒绝):
curl -s -w 'HTTP %{http_code}\n' -X PUT http://127.0.0.1:8132/api/settings \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"title":"Lab Wiki","subtitle":"实验知识库","owner":"Admin User","notice":"Copyright © 2026 Admin","privacy":null,"localization":"zh","timezone":"Asia/Shanghai","template":"light","color":"#1e88e5"}'
HTTP 204
入口二:直接编辑数据文件。settings.json 就在数据集目录下,服务每次处理请求都实时读盘,手工编辑保存后立即生效,无需重启。实测:把 "owner" 从 Admin User 改成 Admin User (file-edit),下一次 GET /api/settings 就返回新值:
sed -i 's/"owner": "Admin User"/"owner": "Admin User (file-edit)"/' /opt/wikidocs/datasets/settings.json
curl -s http://127.0.0.1:8132/api/settings | grep -o '"owner":"[^"]*"'
"owner":"Admin User (file-edit)"
两种入口的取舍:接口方式有完整校验(非法值直接 400 并给出原因),文件方式无任何校验(写错了要到页面异常才发现),日常优先走接口,批量修正或救援场景才直接改文件。
3.3 accounts.json 与 pinned.json 的修改方式
账号与置顶同样支持接口/文件两种入口。账号列表接口 GET /api/accounts(需管理员令牌)返回时会自动剥掉口令摘要字段:
curl -s -w '\nHTTP %{http_code}\n' http://127.0.0.1:8132/api/accounts -H "Authorization: Bearer $JWT"
{"accounts":[{"account":"admin@lab.local","firstname":"Admin","lastname":"User","role":"administrator"},{"account":"author@lab.local","firstname":"Au","lastname":"Thor","role":"author"}]}
HTTP 200
账号的增改走 PUT /api/accounts(详见 5.8),置顶走 PUT /api/pinned(详见 5.10);两者的落盘文件可以直接查看:
cat /opt/wikidocs/datasets/pinned.json
[
{
"path": "guides/quick-start"
}
]
四、参数总览
4.1 环境变量总表(5 项)
| 变量 | 默认值 | 取值与作用 | 生效方式 |
|---|---|---|---|
MODE | public | local / private / public 三态,决定访问与游客令牌行为 | 重建服务进程 |
SECRET | wikidocs-insecure-secret-to-be-changed | 双用途密钥:登录令牌(JWT)签名 + 全部账号口令摘要的 HMAC 密钥 | 重建服务进程 |
PORT | 3210 | 服务内监听端口 | 重建服务进程 |
DATASETS | /var/lib/wikidocs/datasets | 数据集根目录 | 重建服务进程 |
FRONTEND | /app/frontend | 前端静态资源目录(镜像内固定,无需改) | 重建服务进程 |
💡 说明:「重建服务进程」指修改部署编排文件中的
environment:后执行docker compose up -d(会触发 Recreate);Shell 命令行注入的环境变量覆盖不了编排文件里的同名值(实测实录见部署指南 7.3)。SECRET的双用途是本文最重要的结论,轮换影响见 5.2 与 7.1。
4.2 settings.json 字段总表(9 字段)
| 字段 | 类型 | 约束 | 初始化默认值 | 作用 |
|---|---|---|---|---|
title | string | 非空,≤32 字符 | 初始化向导传入值 | 站点标题(浏览器标题与页头主标题) |
subtitle | string | 非空,≤64 字符 | flat-file markdown wiki | 页头副标题 |
owner | string | 非空,≤64 字符 | 初始化向导传入值 | 站点归属方名称 |
notice | string | 非空,≤128 字符 | Copyright © <owner> | 页脚版权/声明文字 |
privacy | string | null | 可空;非空时 ≤1024 字符 | null | 隐私政策横幅内容,null 表示不展示 |
localization | string | 15 个枚举值之一 | en | 界面语言 |
timezone | string | 非空,≤32 字符 | UTC | 时区(如 Asia/Shanghai),影响时间展示 |
template | string | light / dark | light | 明暗主题 |
color | string | 正则 ^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$ | #4caf50 | 主题强调色 |
localization 的 15 个合法枚举值(源码 settings.schema.ts @IsIn 列表,含简体中文 zh):ar、cs、de、en、es、fa、fr、hi、it、ja、nl、pl、pt、ru、zh。
4.3 数据集文件总表
| 路径(DATASETS 下) | 内容 | 修改接口 |
|---|---|---|
settings.json | 站点设置 9 字段 | GET/PUT /api/settings |
accounts.json | 账号数组(含 HMAC 口令摘要) | GET/PUT /api/accounts、GET/PUT /api/profile |
pinned.json | 置顶文档路径数组 | GET/PUT /api/pinned |
documents/ | 文档树(每页一个目录,content.md 正文、_versions/ 版本快照、附件同目录) | /api/document、/api/attachment 等 |
trash/ | 回收站(删除的页带毫秒时间戳前缀暂存) | /api/trash |
五、核心参数分类详解
5.1 MODE:访问模式
MODE 决定整个实例的访问边界,三个取值的实测语义:
local:单机桌面形态(配合官方桌面客户端使用),账号管理接口被禁用——源码accounts.service.ts在该模式下直接抛BadRequestException('Accounts management is disabled in local mode'),服务器部署不使用该值;private:所有页面必须登录,游客令牌端点返回 401(实测回显):
curl -s http://127.0.0.1:8132/api/guest
{"message":"Guest access is enabled only in public mode","error":"Unauthorized","statusCode":401}
public:游客免登录领取只读令牌(86400 秒),匿名浏览全部公开内容,登录后才有写权限:
curl -s http://127.0.0.1:8132/api/guest | head -c 120; echo
{"jwt":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkdXJhdGlvbiI6ODY0MDAsImdlbmVyYXRpb24iOiIyMDI2LTEwLTMwVDA2OjU1OjMyLjMxMloiLCJhY2NvdW50IjoiZ3Vlc3Qi…
当前生效值可用公开端点复核:
curl -s http://127.0.0.1:8132/api/information | head -c 90; echo
{"mode":"public","initialized":true,"service":"wikidocs-backend","version":"2.0.2"
5.2 SECRET:一钥两用的核心密钥
SECRET 在 2.0.2 中承担两个职责(源码实证):
- 登录令牌签名:
authenticate/guest颁发的 JWT 用它签发与校验,换钥后所有已发令牌立即失效; - 口令摘要密钥:账号口令不是裸哈希存储,而是
HMAC-SHA256(key=SECRET, msg=password)(源码accounts.service.ts的hashPassword()用createHmac('sha256', this.environmentService.getSecret()))。也就是说 SECRET 参与了每个账号口令摘要的运算。
用实例数据复算验证(accounts.json 中管理员口令摘要为 86873d8d…6d8):
printf '%s' 'q1w2e3r4' | openssl dgst -sha256 -hmac 'q1w2e3r4-instance-secret-key'
SHA2-256(stdin)= 86873d8d7a8e8dbd33a509af2e0f35c1197aeece7b52bf324e1a5491cf7556d8
与 accounts.json 存储值逐位一致,算法结论成立。因此 SECRET 的轮换规程必须是「换钥 + 重置全部口令」两步:只换钥不重置口令,所有账号(含管理员)都会登录失败(破坏性实测见 7.1)。镜像默认值 wikidocs-insecure-secret-to-be-changed 明确提示必须替换,首次部署时就要定好。
5.3 PORT 与 DATASETS、FRONTEND
PORT:服务内监听端口,默认 3210。2.0 系列从 1.x 的 80 端口迁移过来,官方样例固定 3210;对外暴露端口由部署层的端口映射决定(本文实例为宿主 8132 → 服务内 3210),一般不动PORT本身。启动日志显示的监听地址格式有误导性,判断依据见部署指南 7.4;DATASETS:数据集根目录,全部状态(设置/账号/文档/回收站)都落在它下面。默认/var/lib/wikidocs/datasets,部署层把这个位置挂载到宿主持久化目录即可,无需改值;注意挂载的宿主目录必须预置属主 uid=1000(属主错误导致的 FATAL 重启实录见部署指南 7.1);FRONTEND:前端静态资源在镜像内的位置,/app/frontend,仅源码定制前端时才涉及,运维保持默认。
5.4 站点标识四件套:title / subtitle / owner / notice
四个纯展示字段的约束一致(非空 + 长度上限),超限即 400。以 title(≤32 字符)为例提交 33 个字符:
curl -s -w '\nHTTP %{http_code}\n' -X PUT http://127.0.0.1:8132/api/settings \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"title":"123456789012345678901234567890123","subtitle":"s","owner":"o","notice":"n","privacy":null,"localization":"zh","timezone":"Asia/Shanghai","template":"light","color":"#4caf50"}'
{"message":["title must be shorter than or equal to 32 characters"],"error":"Bad Request","statusCode":400}
HTTP 400
title≤32:站点主标题,建议短词(如「Lab Wiki」),过长会挤压页头布局;subtitle≤64:副标题,一句话说明站点用途(本文实例用「实验知识库」);owner≤64:归属方名称,初始化时默认取管理员姓名;notice≤128:页脚声明,初始化默认生成Copyright © <owner>格式(本文实例为Copyright © 2026 Admin)。
privacy 是其中唯一的可空字段:null 表示不展示隐私横幅;赋非空字符串(≤1024 字符)后客户端会弹出隐私政策横幅,适合对外 public 站点做合规提示。
5.5 localization:界面语言
15 个枚举值之外的任何取值都被拒绝,实测提交 xx:
curl -s -w '\nHTTP %{http_code}\n' -X PUT http://127.0.0.1:8132/api/settings \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"title":"T","subtitle":"s","owner":"o","notice":"n","privacy":null,"localization":"xx","timezone":"Asia/Shanghai","template":"light","color":"#4caf50"}'
{"message":["localization must be one of the following values: ar, cs, de, en, es, fa, fr, hi, it, ja, nl, pl, pt, ru, zh"],"error":"Bad Request","statusCode":400}
HTTP 400
中文界面直接设 "localization": "zh"(本文实例已实测切换,切换后 Web 界面菜单、按钮即时中文化)。注意该值只影响客户端 UI 文案,不翻译文档内容本身。
5.6 timezone:时区
字符串约束(非空、≤32 字符),采用 IANA 时区名。中文环境推荐 Asia/Shanghai(本文实例实测值);留 UTC 时文档时间戳与版本快照时间会与本地时间差 8 小时,容易误判「时间不对」,实为时区展示差异。
5.7 template 与 color:主题外观
template:只有light/dark两个合法值(枚举校验),控制全局明暗主题;color:主题强调色,必须匹配正则^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$,支持 3 位或 6 位十六进制。实测提交颜色名blue被拒:
curl -s -w '\nHTTP %{http_code}\n' -X PUT http://127.0.0.1:8132/api/settings \
-H "Authorization: Bearer $JWT" -H 'Content-Type: application/json' \
-d '{"title":"Lab Wiki","subtitle":"s","owner":"o","notice":"n","privacy":null,"localization":"zh","timezone":"Asia/Shanghai","template":"light","color":"blue"}'
{"message":["color must match /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/ regular expression"],"error":"Bad Request","statusCode":400}
HTTP 400
合法写法如 #1e88e5(本文实例采用)或简写 #1e8。本文实例曾将 template 切为 dark、color 设为 #1e88e5 并 PUT 成功(204),确认两值可独立组合。
5.8 账号参数:accounts.json 字段与角色枚举
账号文件是对象数组,每条账号 5 个字段:
| 字段 | 约束 | 说明 |
|---|---|---|
account | 邮箱格式(@IsEmail),≤256 字符 | 登录名,本文实例用 admin@lab.local |
firstname / lastname | 非空,各 ≤32 字符 | 姓与名,展示用 |
role | administrator / author / user 三枚举 | 角色决定授权范围 |
password | 可选(null 表示禁用登录);存储值为 HMAC 摘要 | 新建账号必填(接口侧校验) |
实际落盘内容(口令摘要为 HMAC-SHA256,见 5.2):
cat /opt/wikidocs/datasets/accounts.json
[
{
"account": "admin@lab.local",
"firstname": "Admin",
"lastname": "User",
"role": "administrator",
"password": "86873d8d7a8e8dbd33a509af2e0f35c1197aeece7b52bf324e1a5491cf7556d8"
},
{
"account": "author@lab.local",
"firstname": "Au",
"lastname": "Thor",
"role": "author",
"password": "86873d8d7a8e8dbd33a509af2e0f35c1197aeece7b52bf324e1a5491cf7556d8"
}
]
角色语义:administrator 拿到 read/write/delete/sync/manage 全量授权(JWT authorizations 字段实测可见),author 与 user 按角色收敛写与管理权限;账号增改统一走 PUT /api/accounts(接口会自动完成摘要运算,不要手工编辑 accounts.json 写口令)。
5.9 文档路径规则:sanitizeDocumentPath
文档路径不是自由文本,接口层有一套确定性清洗规则(源码 environment.service.ts),决定 documents/ 下的目录命名。规则逐条如下:
- 去除首尾空白后整体转小写;
- 反斜杠
\统一替换为/; - 去掉首尾斜杠,连续斜杠合并为一个;
- 合法字符仅
a-z 0-9 _ . - /,其余字符(含中文、空格、大写字母)一律替换为-; - 连续
-合并为一个; - 含
..直接拒绝:Invalid path <…>, '..' is not allowed(防目录穿越); - 路径中含
_versions直接拒绝:Invalid path <…>, '_versions' is not allowed(保护版本快照目录)。
对中文标题的实际影响:指南/部署说明 这类路径清洗后变成 ---/----,可读性差且易撞名。建议建页时直接用英文小写路径(如 guides/quick-start),把中文放在文档 title 元数据里——本文实例的示例页就用这种姿势落盘:
find /opt/wikidocs/datasets/documents -name content.md | sort
/opt/wikidocs/datasets/documents/content.md
/opt/wikidocs/datasets/documents/guides/quick-start/content.md
5.10 pinned.json:置顶列表
置顶是轻量的路径数组,每项只有 path 一个字段,值必须是清洗后的合法文档路径(见 5.9)。本文实例把示例页置顶后的落盘内容见 3.3([{"path": "guides/quick-start"}])。接口侧对应 PUT /api/pinned;手工编辑该文件同样即时生效,但路径写错(未清洗或不存在)会导致置顶项在客户端无法跳转。
六、生产配置模板
适用场景:小团队私有知识库——20 人以内、日均编辑几十次、文档量数千页以内。资源口径:2 vCPU / 4GB 内存 / 20GB+ 数据盘(WikiDocs 进程为 Node.js 单进程、无数据库,空闲内存占用约 38MB(/api/information 实测 memory:38514688),资源瓶颈主要在磁盘 IO 与附件体积,4GB 内存余量充足)。
部署层模板(生产环境 MODE 用 private,SECRET 必须换成随机长串):
name: wikidocs-2.0.2-stack
services:
wikidocs:
image: zavy86/wikidocs:2
container_name: wikidocs-2.0.2-web
environment:
MODE: private
SECRET: ${WIKIDOCS_SECRET}
PORT: "3210"
volumes:
- /opt/wikidocs/datasets:/var/lib/wikidocs/datasets
ports:
- "8132:3210"
restart: unless-stopped
settings.json 模板(中文团队推荐值):
{
"title": "团队知识库",
"subtitle": "研发与运维知识沉淀",
"owner": "IT 部",
"notice": "Copyright © 2026 IT 部 - 内部资料",
"privacy": null,
"localization": "zh",
"timezone": "Asia/Shanghai",
"template": "light",
"color": "#1e88e5"
}
逐项说明:
MODE: private:内部知识库默认全站登录;确需对外公开再切public并配合privacy横幅(5.4);SECRET:${WIKIDOCS_SECRET}从部署环境的同名 Shell 变量填充(先export WIKIDOCS_SECRET=$(openssl rand -hex 32)再执行docker compose up -d),一旦投入生产就不再轮换(轮换代价见 7.1),密钥本身不要提交到代码仓库;localization: zh+timezone: Asia/Shanghai:中文团队的界面与时区基线(5.5、5.6);template/color按团队偏好,light+#1e88e5是低刺激的默认组合(5.7)。
七、常见问题(FAQ)
以下 5 个问题均为本次配置实测踩到或验证过的真实场景,处理方案附原始回显。
7.1 更换 SECRET 后所有账号登录失败
现象:把 SECRET 从 q1w2e3r4-instance-secret-key 改为 rotated-secret-for-test 并重建服务后,口令完全正确的管理员登录也报错:
curl -s -w '\nHTTP %{http_code}\n' -X POST http://127.0.0.1:8132/api/authenticate \
-H 'Content-Type: application/json' \
-d '{"account":"admin@lab.local","password":"q1w2e3r4"}'
{"message":"Authentication failed","error":"Unauthorized","statusCode":401}
HTTP 401
定位:SECRET 是口令摘要的 HMAC 密钥(5.2),换钥后 accounts.json 里存量摘要全部失配,校验必然失败——这是机制性结果,不是密码记错。
修复:二选一。
- 实验环境直接把 SECRET 改回原值重建,登录即刻恢复(本文实测恢复后
HTTP 200); - 生产确需轮换:改 SECRET 重建后,用管理员之外的手段(如
PUT /api/accounts)重置全部账号口令,让摘要按新钥重算。所以生产环境应「一次定好、长期不动」。
7.2 PUT /api/settings 返回 400
现象:提交设置被拒。三类高频 400 的实测回显(均在 5.4–5.7 出现过):
{"message":["title must be shorter than or equal to 32 characters"],"error":"Bad Request","statusCode":400}
{"message":["localization must be one of the following values: ar, cs, de, en, es, fa, fr, hi, it, ja, nl, pl, pt, ru, zh"],"error":"Bad Request","statusCode":400}
{"message":["color must match /^#(?:[0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/ regular expression"],"error":"Bad Request","statusCode":400}
修复:按 message 数组逐条对号——长度超限就截短、语言用 15 枚举内的值、颜色必须 # 开头的 3/6 位十六进制。另注意 PUT 是全量提交:只提交改动字段(如 {"title":"T"})会因缺字段被 400,正确姿势是先 GET 取全量、改完整体提交(3.2 实测的 204 流程)。
7.3 手工编辑 settings.json 后不生效?
结论:会生效,且无需重启——服务对 settings.json 是按请求实时读盘(3.3 实测:改完 owner 立即在下一次 GET /api/settings 返回新值)。如果「没生效」,先检查三件事:改的是不是挂载进数据集的那个文件(DATASETS 指向的真实路径,而非编排目录里的散文件)、JSON 是否被改坏(python3 -m json.tool settings.json 可校验语法)、浏览器端是否有界面缓存(强制刷新)。
7.4 数据目录属主不对导致 FATAL 无限重启
现象:改动 DATASETS 挂载后服务反复重启,日志刷 FATAL [Bootstrap] DATASETS directory </var/lib/wikidocs/datasets> is not writable。
修复:宿主数据目录预置属主 uid=1000(服务以 node 用户运行):
chown -R 1000:1000 /opt/wikidocs/datasets
完整的定位链路(含 User: [node] 与 uid=1000 的取证命令)见 《WikiDocs 2.0 Docker Compose 部署指南》7.1。
7.5 忘记管理员口令怎么办
现象:管理员口令遗失,无法登录。
修复:直接重算 accounts.json 中该账号的 password 摘要。摘要算法为 HMAC-SHA256(key=SECRET, msg=新口令)(5.2 实测验证过的命令):
printf '%s' 'q1w2e3r4' | openssl dgst -sha256 -hmac 'q1w2e3r4-instance-secret-key'
SHA2-256(stdin)= 86873d8d7a8e8dbd33a509af2e0f35c1197aeece7b52bf324e1a5491cf7556d8
把输出值替换进 accounts.json 对应账号的 password 字段即可(文件实时生效,无需重启)。更省事的路径:若还有另一个管理员账号,用 PUT /api/accounts 重置口令(接口自动算摘要),不必碰文件。
八、参考链接
- 官方仓库(参数源码所在分支 main):https://github.com/Zavy86/WikiDocs
- 官方数据集与自托管说明(README):https://github.com/Zavy86/WikiDocs#self-hosted
- 接口文档(实例自带 Swagger):
http://<服务器IP>:8132/api/ - 本系列文档:《WikiDocs 介绍与选型指南》、《WikiDocs 2.0 Docker Compose 部署指南》
- 同类组件配置实测:《PmWiki 配置参数详解》、《Otter Wiki 配置参数详解》