SiYuan 自托管知识工作空间:从架构、Docker 部署到内置 CLI 的完整实践指南
Siyuan 是一个隐私优先、完全开源、可自托管的个人知识管理工作空间,支持块级(Block)引用与双向链接、Markdown WYSIWYG 所见即所得编辑。本篇以仓库 README 为核心骨架,结合内核源码逐层展开:先讲清 Siyuan 的定位与功能边界,再给出 Docker 自托管部署的完整参数与排错要点,最后深入内置命令行工具(CLI)与数据工作空间的结构,读完后你可以独立完成服务端部署、用命令行直接读写工作空间数据,并理解 .sy 文件在磁盘上的组织方式。
项目定位与核心功能
Siyuan 的官方定位是 "privacy-first personal knowledge management system"(隐私优先的个人知识管理系统),强调两个核心技术特性:细粒度的块级引用与 Markdown WYSIWYG 编辑。绝大多数功能免费开放,即使商业使用也无需付费,仅部分云同步、会员权益类功能需要付费。
按 README 梳理的功能全景如下,每一类能力在仓库中都有对应的实现模块:
- 内容块:块级引用与双向链接、自定义属性、SQL 查询嵌入(数据库视图)、
siyuan://协议。内核侧对应kernel/av/(Attribute View 属性视图引擎,支持表格/看板/画廊布局)与kernel/sql/(内嵌 SQLite + FTS5 全文检索)。 - 编辑器:块级编辑、Markdown 所见即所得、列表大纲、块聚焦(zoom-in)、百万字级大文档编辑、公式/图表/流程图/Gantt 图/五线谱、网页剪藏、PDF 批注链接。前端编辑器代码位于
app/src/protyle/(WYSIWYG、工具栏、面包屑、撤销等模块);编辑引擎本身是独立项目 lute(Kramdown/Markdown AST),以 GopherJS 构建的lute.min.js形式打进前端。 - 导出:块引用与嵌入导出、带资源的标准 Markdown、PDF/Word/HTML,以及面向公众号、知乎、语雀的富文本复制。
- 其他:数据库表格视图、闪卡间隔重复(SRS)、基于 OpenAI API 的 AI 写作与问答、Tesseract OCR、多标签与拖拽分屏、模板片段、JavaScript/CSS 自定义代码片段、Android/iOS/HarmonyOS 原生应用、Docker 部署、完整 HTTP API(见 API 文档)以及社区市场(Bazaar,插件/主题/图标/模板分发)。
架构与周边生态
从源码结构看,本仓库是一个"Go 内核 + TypeScript 前端"的双体结构:
kernel/:Go 后端,包含 HTTP 服务、数据引擎、API(约 400 个路由端点,入口在kernel/api/router.go)、SQLite 索引、搜索、属性视图、插件系统、MCP 服务、AI Agent 运行时等全部领域逻辑;app/:TypeScript 前端(Electron/web),由 webpack 构建到app/stage/build/供内核分发;- 另有一个独立的
export构建包(全局Protyle,入口app/src/protyle/method.ts),专用于在导出的 HTML / PDF 预览页中渲染代码高亮、KaTeX 公式与 Mermaid 等富内容。
围绕 Siyuan 还有一组独立仓库组成的生态:编辑器引擎 lute、浏览器剪藏扩展 siyuan-chrome、社区市场 bazaar、数据仓库同步引擎 dejavu(加密快照)、插件 API 声明 petal、三端原生应用(siyuan-android / siyuan-ios / siyuan-harmony,均为封装 gomobile 内核的独立原生工程)、间隔重复调度器 riff。本仓库承载内核与 Electron/web 端,其余项目各自维护独立工具链。版本信息以 kernel/go.mod、app/package.json 与 kernel/util/working.go 为准,更新记录见 CHANGELOG.md。
获取与安装方式
README 推荐的获取优先级是"桌面与移动端优先走应用商店",以便未来一键升级:
- 移动端:App Store、Google Play、F-Droid 均可获取 Siyuan 应用;
- 桌面端:Microsoft Store 提供 Windows 版本;
- 安装包:可从 B3log 官网或 GitHub Releases 下载各平台安装包;
- 包管理器:发行版中以
siyuan与siyuan-note两个包名被多个包管理器收录,可用dnf/apt/brew等常规方式检索安装。
升级路径上:商店安装的用户走商店更新;桌面安装包用户可在"设置 - 关于"中开启"自动下载更新安装包",由客户端自动下载并提示安装;手动安装的用户需重新下载安装包。Docker 用户拉取新镜像即可。重大版本更新前,官方会先发布 Insider 预览版。
Docker 自托管部署
服务端部署最简单的方式就是 Docker。镜像为 b3log/siyuan。仓库根目录的 Dockerfile 揭示了三阶段构建过程:先用 node:22 构建前端产物(pnpm run build 并裁剪 changelogs),再用 golang:1.26-alpine 编译内核(注意构建时带 fts5 标签启用 SQLite 全文检索扩展),最终产物落在 alpine 运行时中。
容器内文件结构
整个程序位于 /opt/siyuan/,与 Electron 安装包中 resources/ 目录的结构基本一致:
appearance/:图标、主题、语言包guide/:用户指南文档stage/:界面与静态资源kernel/:内核程序(即 CLI 可执行文件)
Dockerfile 中声明了 EXPOSE 6806、ENV HOME=/home/siyuan、ENV RUN_IN_CONTAINER=true,入口点为 ENTRYPOINT ["/opt/siyuan/entrypoint.sh"],默认 CMD ["/opt/siyuan/kernel", "serve"]。
Entrypoint 与 PUID/PGID 权限模型
kernel/entrypoint.sh 是解决"宿主机挂载目录权限"的关键脚本,其逻辑可以逐段印证:
- 读取环境变量,
PUID/PGID未提供时默认均为1000,用户/组名默认siyuan; - 通过
getent检查系统是否已存在该 UID/GID 的用户与组,不存在则用addgroup/adduser创建; - 解析命令行参数:识别
--workspace=参数并将其余参数原样保留到ARGS;若设置了SIYUAN_WORKSPACE_PATH环境变量则优先作为工作空间路径; - 对
/opt/siyuan、/home/siyuan/与目标工作空间目录执行chown -R ${PUID}:${PGID}; - 最终以
exec su-exec "${PUID}:${PGID}" /opt/siyuan/kernel --workspace=... ${ARGS}切换用户启动内核。
这意味着你无需在 docker run 或 compose 中手动传 -u,容器会在启动时动态调整用户与组。相应地,宿主机创建工作空间目录时应把属主对齐你打算使用的 PUID/PGID,例如:
chown -R 1001:1002 /siyuan/workspace
启动参数(v3.7.0 起必须显式传 serve)
注意:自 v3.7.0 起,
serve子命令必须显式传入(例如docker run b3log/siyuan serve --workspace=...)。可用docker run --rm b3log/siyuan serve --help查看全部服务选项。
这一约束与源码行为一致:Dockerfile 中的注释明确说明"若通过 docker run / command: 传额外参数,需自行带上 serve 子命令,否则用户参数会整体覆盖 CMD"。而 serve 子命令自身的完整参数定义在 serve 子命令:--wd(工作目录,默认取内核可执行文件上一级)、--port、--readonly、--accessAuthCode(锁屏密码)、--lang(支持 ar/de/en/es/fr/he/hi/id/it/ja/ko/nl/pl/pt-BR/ru/sk/th/tr/uk/zh-CN/zh-TW,也兼容 zh_CN/en_US 等下划线旧值)、--mode(dev/prod)、--ssl、--attach-ui、--safe-mode。
README 给出的关键参数与环境变量:
| 参数/变量 | 说明 |
|---|---|
--workspace | 工作空间文件夹路径,需通过 -v 挂载进容器 |
SIYUAN_WORKSPACE_PATH | 环境变量方式指定工作空间;同时设置时命令行优先 |
--accessAuthCode | 锁屏密码(务必修改,否则任何人都能访问你的数据) |
SIYUAN_ACCESS_AUTH_CODE | 环境变量方式设置锁屏密码;命令行优先 |
SIYUAN_ACCESS_AUTH_CODE_BYPASS=true | 关闭锁屏密码校验 |
SIYUAN_LANG | 界面语言,接受 BCP 47 标签如 zh-CN/zh-TW/en/ja/pt-BR;Docker 下默认 en。不设置则沿用"设置"里已保存的语言;设置后每次启动都会覆盖已保存设置。命令行 --lang 优先于该变量 |
PUID / PGID | 容器内运行用户的 UID/GID,默认均为 1000 |
基础启动命令:
docker run -d \
-v workspace_dir_host:workspace_dir_container \
-p 6806:6806 \
-e PUID=1001 -e PGID=1002 \
b3log/siyuan \
serve \
--workspace=workspace_dir_container \
--accessAuthCode=xxx
其中 workspace_dir_host 为宿主机上的工作空间路径,workspace_dir_container 为容器内路径(即 --workspace 指定的值)。为简化运维,推荐宿主与容器使用相同路径,例如都设为 /siyuan/workspace:
docker run -d \
-v /siyuan/workspace:/siyuan/workspace \
-p 6806:6806 \
-e PUID=1001 -e PGID=1002 \
b3log/siyuan \
serve \
--workspace=/siyuan/workspace/ \
--accessAuthCode=xxx
Docker Compose 示例
version: "3.9"
services:
main:
image: b3log/siyuan
command: ['serve', '--workspace=/siyuan/workspace/', '--accessAuthCode=${AuthCode}']
ports:
- 6806:6806
volumes:
- /siyuan/workspace:/siyuan/workspace
restart: unless-stopped
environment:
- TZ=${YOUR_TIME_ZONE} # 时区标识,可参照 tz database 时区列表
- PUID=${YOUR_USER_PUID} # 自定义用户 ID
- PGID=${YOUR_USER_PGID} # 自定义组 ID
PUID/PGID 未提供时容器内默认使用 1000。由于 entrypoint 会依据这两个变量动态创建/复用用户组,compose 中不必再显式写 user: '1000:1000'。
隐藏端口、注意事项与功能限制
- 对外隐藏 6806 端口时用 Nginx 反向代理,并注意为
/ws路径配置 WebSocket 反向代理(内核与前端通过 WebSocket 推送实时状态,见kernel/util/websocket.go); - 务必确认挂载卷正确,否则容器删除后数据丢失;
- 不要用 URL 重写方式做跳转,否则可能出现认证问题,推荐配置反向代理;
- 遇到权限问题时,核对
PUID/PGID是否与宿主机挂载目录的属主一致; - 功能限制(服务端模式):不支持桌面与移动应用连接,仅支持浏览器访问;不支持导出 PDF/HTML/Word;不支持导入 Markdown 文件。
Unraid 与 TrueNAS
Unraid:先在终端执行 chown -R 1000:1000 /mnt/user/appdata/siyuan,然后按以下模板配置(Web UI 端口 6806、容器端口 6806、容器路径 /home/siyuan、宿主机路径 /mnt/user/appdata/siyuan、PUID/PGID 均 1000、发布参数 serve --accessAuthCode=******)。
TrueNAS:先在 Shell 中创建并授权数据集(按实际数据集路径替换 Pool_1/Apps_Data/siyuan):
zfs create Pool_1/Apps_Data/siyuan
chown -R 1001:1002 /mnt/Pool_1/Apps_Data/siyuan
chmod 755 /mnt/Pool_1/Apps_Data/siyuan
再到 Apps - DiscoverApps - More Options - Install via YAML 按 YAML 安装:
services:
siyuan:
image: b3log/siyuan
container_name: siyuan
command: ['serve', '--workspace=/siyuan/workspace/', '--accessAuthCode=2222']
ports:
- 6806:6806
volumes:
- /mnt/Pool_1/Apps_Data/siyuan:/siyuan/workspace # 调整为你的数据集路径
restart: unless-stopped
environment:
- TZ=America/New_York # 按需替换为你的时区
- PUID=1001
- PGID=1002
内置命令行接口(CLI)
内核二进制本身就是一套完整的 CLI,可无需启动服务进程直接读写工作空间数据,适合脚本化运维、批量迁移与 Agent 自动化。入口在 kernel/main.go,它仅一行核心逻辑:调用 cmd.Execute()(Cobra 命令树),而所有子命令与全局行为定义在 kernel/cli/cmd/ 包中(README 命令表与 cli/cmd 目录 中的文件一一对应)。
快速上手
# 列出所有笔记本
siyuan notebook list -w ~/SiYuan
# 全文搜索(JSON 输出)
siyuan search "keyword" -w ~/SiYuan -f json
# 在资源文件内容中搜索(PDF/Word/Excel/txt 等)
siyuan search "phrase" --asset -w ~/SiYuan
siyuan search "phrase" --asset --ext pdf --ext docx -w ~/SiYuan
# 将文档导出为 Markdown
siyuan export md --id <block-id> -w ~/SiYuan
这些全局参数在 CLI 根命令 的 init() 中注册:
-w, --workspace:工作空间路径;未提供时依次回退到环境变量SIYUAN_WORKSPACE_PATH,再到~/SiYuan,并校验该目录确实是一个合法工作空间;-f, --format:输出格式table(默认)或json,json便于脚本消费;--dry-run:校验并打印将要发生的变更而不实际执行,绝大多数"变更类"命令都支持;--log-level:off | trace | debug | info | warn | error | fatal,CLI 单次命令默认warn以减少初始化日志噪声,serve子命令则跟随conf.json的system.logLevel。
两个值得注意的源码级细节:
- 写完即可搜:根命令的
PersistentPostRunE在每条 CLI 命令结束后主动调用model.FlushTxQueue()与sql.FlushQueue()(见 root.go)。因为一次性进程没有 server 模式的定时 flush,若不落库,索引队列只能等下次启动才恢复。 - 加密笔记本不可经 CLI 操作:
rejectEncryptedNotebookCLI会拦截指向加密笔记本的命令(含--notebook/--id/--block等参数及file/asset的路径参数),加密笔记本只能通过应用内专用流程解锁,避免 CLI 成为明文/密文旁路。
命令分类速查表
| 分类 | 命令 | 说明 |
|---|---|---|
| 笔记本与文档 | notebook、document、dailynote | 增删改查与每日笔记 |
| 内容 | block、attr、outline | 块读写、属性、大纲 |
| 元数据 | tag、bookmark、template | 标签、书签、模板片段 |
| 查询 | search、sql | 全文、语义、资源内容检索与 SQL 查询 |
| 引用 | ref | 反向链接与提及 |
| 导入/导出 | export、import、inbox | Markdown、HTML、预览、Word、.sy.zip、Data、云端收件箱 |
| 数据管理 | repo、history、sync | 快照、版本、云同步 |
| 工具 | asset、file | 资源与文件系统 |
| 数据库 | database | 属性视图管理 |
| 服务器 | serve | 启动内核 HTTP 服务 |
| 工作空间与系统 | workspace、system | 列出、检查、系统信息 |
完整命令树可执行 siyuan --help 查看。以 search 为例,search 子命令 还支持 --method(其中 method 4 走 model.SemanticSearchBlock 语义检索)、--notebook/--path/--type/--subtype 过滤、--group-by 分组与分页参数,默认页大小为 32;--asset 模式则调用 model.FullTextSearchAssetContent 检索资源文件正文,--get-asset 可按路径取单个已索引资源全文。notebook 子命令的 create/remove 等均支持 --dry-run,变更成功后还会调用 model.AppendPushReloadFiletreeEntry() 通知在线端刷新文件树。
CLI 安装方式
CLI 二进制位于 <install-dir>/resources/kernel/SiYuan-Kernel,通过 siyuan 命令调用:
-
Windows:安装程序自动将内核目录加入
PATH,开箱即用。Microsoft Store 版运行在 MSIX 沙箱中无法修改PATH,需部署一个一次性siyuan.cmdshim(可随 Store 更新存活):# 仅 Microsoft Store 版 — PowerShell 中执行一次 $shimDir = "$env:LOCALAPPDATA\Microsoft\WindowsApps" # 默认已在 PATH 中 @( '@echo off' 'setlocal' 'set "ROOT="' 'for /f "delims=" %%i in (''powershell -NoProfile -Command "(Get-AppxPackage *SiYuan*).InstallLocation"'') do set "ROOT=%%i"' 'if not defined ROOT goto :noshim' '"%ROOT%\app\resources\kernel\SiYuan-Kernel.exe" %*' 'exit /b %ERRORLEVEL%' ':noshim' '1>&2 echo siyuan: Microsoft Store edition not found' 'exit /b 1' ) | Set-Content "$shimDir\siyuan.cmd"卸载时移除:
Remove-Item "$env:LOCALAPPDATA\Microsoft\WindowsApps\siyuan.cmd"。 -
macOS:安装后建立符号链接:
ln -s /Applications/SiYuan.app/Contents/Resources/kernel/SiYuan-Kernel /usr/local/bin/siyuan -
Linux:安装后建立符号链接:
ln -s <install-dir>/resources/kernel/SiYuan-Kernel /usr/local/bin/siyuan
数据如何存储:工作空间结构
README 的 FAQ 给出了工作空间数据目录的一级概览:assets(插入的资源)、emojis(表情图片)、snippets(代码片段)、storage(查询条件、布局、闪卡等)、templates(模板片段)、widgets(小部件)、plugins(插件)、public(公共数据),其余文件夹即用户创建的笔记本,其中的 .sy 文件以 JSON 格式保存文档数据。
仓库内 WORKSPACE.md 对此有更完整的权威描述,其核心结论是:Siyuan 工作空间是一个自描述的目录树,文件名即 ID,目录结构即文档层级——不存在记录"文档在哪里"的二进制数据库,文件系统本身就是唯一事实源。目录速览:
<workspace root>/
├── conf/conf.json # 工作空间级配置(含 kernelVersion 字段,是判定合法工作空间的依据)
├── data/ # 所有笔记本数据的根
│ ├── assets/ templates/ widgets/ plugins/ emojis/ snippets/ public/ storage/
│ └── <boxID>/ # 笔记本(目录名即笔记本 ID)
│ ├── .siyuan/conf.json # 笔记本配置(名称/图标/关闭状态)
│ ├── <docID>.sy # 文档(JSON 树,文件名即文档根 ID)
│ └── <docID>/ # 同名子目录存放该文档的全部子文档,可任意嵌套
├── repo/ # 数据仓库(快照/同步)
├── history/ # 编辑历史归档
└── temp/ # 临时/导出文件
其中最重要的约定是"文档 A 的磁盘表示 = A.sy 文件 + A/ 同名目录",所有子文档都在同名目录内嵌套。由此可推断出运维风险:移动或重命名有子文档的文档时必须连同同名目录一起操作,否则子文档会被"孤儿化"。.sy 文件内部的 JSON 块级结构则见 SY-FORMAT.md;data/storage/ 下的 SQLite 数据库(siyuan.db 等)是索引缓存,由 kernel/sql/ 维护,理论上可重建,真正的源数据是 .sy 文件本身。
仓库自带的 guide/ 目录即产品内置的用户指南工作空间实例,包含真实结构的 .sy 文档、assets/ 资源与 storage/ 索引,可直接打开观察。
常见问题(FAQ)
- 是否支持第三方同步盘(如网盘)同步数据? 不支持,否则可能损坏数据。虽然不支持同步盘,但会员功能支持连接第三方云存储;也可以手动导出/导入实现迁移(桌面端:设置 - 导出 - 导出数据/导入数据;移动端:右列 - 关于 - 导出/导入数据)。
- Siyuan 是开源的吗? 完全开源,UI 与内核、Android、iOS、HarmonyOS 及 Chrome 剪藏扩展均在独立仓库公开,欢迎贡献;开发贡献规范见仓库内的 CONTRIBUTING 指南。
- 列表项下的段落等块找不到块图标怎么办? 列表项下第一个子块会省略块图标,将光标移入该块并按
Ctrl+/即可唤出块菜单。 - 数据仓库密钥(data repo key)丢失怎么办? 若多端此前已正确初始化,各端密钥相同,可在"设置 - 关于 - 数据仓库密钥 - 复制密钥字符串"找回。若从未正确配置或所有设备均不可用,则需重置:先用"导出数据"或直接复制文件系统上的
workspace/data/目录手动备份;再执行"设置 - 关于 - 数据仓库密钥 - 重置数据仓库";随后重新初始化密钥(一端初始化后,其他端导入该密钥);云端改用新的同步目录,旧的同步目录与快照即失效可删除。 - 需要付费吗? 大多数功能免费,即使商业使用也免费;会员权益需付费后使用。
延伸阅读路径
- README.md:本篇的基础文档,另有 中文、日文、土耳其文 版本
- API.md:内核 HTTP API 全集(剪藏扩展、自定义脚本均依赖它)
- WORKSPACE.md 与 SY-FORMAT.md:工作空间磁盘布局与
.sy块级 JSON 格式 - ENCRYPTED-NOTEBOOK.md:加密笔记本机制(CLI 侧对其有操作限制,原因见上文)
- Dockerfile 与 kernel/entrypoint.sh:服务端镜像构建与权限模型的一手源码
- kernel/cli/cmd:全部 CLI 子命令实现,kernel/main.go 为进程入口
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




