NAS 手把手部署 Fast Note Sync——Obsidian 实时同步与 Perlite 网页发布
2026/8/26 19:39:17 网站建设 项目流程

ℹ️ 读者定位

适合你,如果:你有一台支持 Docker Compose 的服务器(也可以是Nas),正在使用 Obsidian,希望把多端同步服务和网页只读浏览都放在自己家里。

开始前需要:云服务器管理权限、SSH 或容器管理器、基础命令行能力,以及一份已经验证可恢复的 Obsidian 备份。

读完可以完成:跑通 Fast Note Sync 服务端、把指定 Vault 同步到 云服务器 本地目录,再通过 Perlite 从浏览器只读查看。

暂时不适合:完全不熟悉 Docker、还没有做任何备份,或者准备把90008090端口直接裸露到公网的人。ARM64 云服务器 还要先解决 Perlite 官方镜像兼容性。

📄 这篇文章最终要跑通什么

数据链路是:Obsidian → Fast Note Sync Service → FastNodeSync-CLI → NAS Vault → Perlite → Nginx

部署顺序是:先启动 FNS,创建 Vault 和 Token;再让 CLI 首次只拉取;确认文件正确后,最后开启常驻双向同步和网页发布。

这篇内容分为以下几个部分:

  1. 先讲清四个服务分别做什么。
  2. 修正原始 Compose 的结构问题。
  3. 按三阶段顺序部署。
  4. 连接 Obsidian,并完成三层验收。
  5. 处理 ARM 架构、安全、备份和升级问题。

一、先看懂这套部署

1.1. Fast Note Sync 解决什么问题

Fast Note Sync 不是简单的网盘文件夹同步。它由服务端和客户端协作,通过 WebSocket 把笔记、附件、目录变化以及可选的 Obsidian 配置同步到多个设备。

在这套方案里,FNS 服务端负责接收和分发变化;Obsidian 插件负责电脑、手机端同步;FastNodeSync-CLI 负责把服务端 Vault 落到 云服务器 的普通文件夹。

这里一定要注意:FNS 服务端自己的storage不是给 Perlite 直接读取的标准 Obsidian Vault。所以中间需要 CLI,把内容还原成普通 Markdown 目录。

1.2. 四个服务分别做什么

服务核心职责宿主机端口关键挂载权限
fast-note-sync-serviceWeb 管理、REST、WebSocket、同步数据保存9000storage、服务端config读写
fns-cli把远端 Vault 同步成 云服务器 本地文件夹CLIconfigvault配置只读、Vault 读写
perlite把 Markdown Vault 解析成网页同一个vault只读
perlite_web用 Nginx 暴露 Perlite 页面8090perlite.conf只读

perliteperlite_web是两个容器,是因为 Perlite 镜像运行 PHP-FPM,而 Nginx 负责接收浏览器请求。


NAS 中四个服务的职责与共享 Vault

1.3. 最终数据流


Fast Note Sync 在 NAS 上的端到端架构

从图里可以看到两种完全不同的数据方向:

  • Obsidian、FNS 和 CLI 之间是双向同步
  • 云服务器 Vault 到 Perlite 是只读展示

⚠️ 同步不是备份

双向同步会快速传播正常修改,也会传播误删除和错误修改。部署同步之前先做备份,部署成功后仍然要保留独立快照和离线副本。

二、先修正原始 Compose

2.1. 原始文件有哪些问题

你提供的思路是对的,但 YAML 不能直接运行:

问题会造成什么结果修正方式
顶层services:重复三次服务被错误嵌套,Compose 无法解析只保留一个顶层services:
服务端第二条 volume 没有缩进config挂载不属于服务对齐到volumes:列表
depends_on列表缩进错误Nginx 依赖关系无效- perlite:ro放到depends_on
服务端和 CLI 共用./config两套同名、不同结构的配置互相污染拆成fast-note-sync/configfns-cli/config
fns-cli直接写build: .Compose 不在源码根目录时找不到 Dockerfile明确build.context: ./fns-cli
CLI 与 Perlite 使用不同宿主机路径两者看到的可能不是同一个 Vault统一使用./fns-cli/vault
第一次直接启动全部服务CLI 没有 Token,会反复认证失败分阶段启动
version: "3"Compose V2 会提示该字段已经过时当前示例直接省略

先执行下面的命令,是排查 Compose 最省时间的一步:

dockercompose config

只要这里报错,就不要继续up -d

2.2. 推荐目录结构

本文假设 Compose 放在:

/home/caimingyang/obsidian/

最终目录如下:

/home/caimingyang/obsidian/ ├── docker-compose.yml ├── fast-note-sync/ │ ├── config/ │ └── storage/ ├── fns-cli/ │ ├── Dockerfile │ ├── requirements.txt │ ├── fns_cli/ │ ├── config/ │ │ └── config.yaml │ └── vault/ └── perlite/ └── perlite.conf

这样处理以后:

  • 服务端数据在fast-note-sync/
  • CLI 源码、配置和 Vault 在fns-cli/
  • CLI 读写fns-cli/vault
  • Perlite 只读同一个fns-cli/vault

2.3. 修正后的完整 Compose

可直接复制的文件已经保存到:

01-素材/部署示例/docker-compose.yml

完整内容如下:

services: fast-note-sync-service: image: haierkeys/fast-note-sync-service:latest container_name: fast-note-sync-service restart: always ports: -"9000:9000"volumes: - ./fast-note-sync/storage:/fast-note-sync/storage - ./fast-note-sync/config:/fast-note-sync/config fns-cli: build: context: ./fns-cli dockerfile: Dockerfile container_name: fns-cli restart: unless-stopped environment: -PYTHONUNBUFFERED=1volumes: - ./fns-cli/config:/app/config:ro - ./fns-cli/vault:/app/vault:rw depends_on: - fast-note-sync-service perlite: image: sec77/perlite:latest container_name: perlite restart: unless-stopped environment: NOTES_PATH:"Notes"HIDE_FOLDERS:".obsidian,.git,private,trash,templates"HIDDEN_FILE_ACCESS:"false"LINE_BREAKS:"true"ABSOLUTE_PATHS:"false"NICE_LINKS:"true"SHOW_TOC:"true"SHOW_LOCAL_GRAPH:"false"DISABLE_POP_HOVER:"true"HTML_SAFE_MODE:"true"ZETTELKASTEN_FILENAMES_ENABLED:"false"HOME_FILE:"README"FONT_SIZE:"16"SITE_TITLE:"我的笔记"SITE_NAME:"Obsidian 知识库"SITE_TYPE:"article"ALLOWED_FILE_LINK_TYPES:"pdf,mp4,webm,mp3,m4a,doc,docx,xls,xlsx,zip,png,jpg,jpeg,gif,webp,svg"HIGHLIGHTJS_LANGS:"java,javascript,typescript,sql,bash,powershell,yaml,json,xml,python,go,c,cpp"volumes: - ./fns-cli/vault:/var/www/perlite/Notes:ro perlite_web: image: nginx:stable container_name: perlite_web restart: unless-stopped ports: -"8090:80"volumes: - ./perlite/perlite.conf:/etc/nginx/conf.d/default.conf:ro volumes_from: - perlite:ro depends_on: - perlite networks: default: name: obsidian-fns

💡 为什么 CLI 使用内部服务名

fns-cli与 FNS 在同一个 Compose 网络里,所以 API 地址直接写http://fast-note-sync-service:9000。不要让容器绕到公网域名再访问同一台 云服务器。

三、准备 云服务器 环境

3.1. 先检查四件事

登录 云服务器 SSH 后执行:

uname-mdockerversiondockercompose versiondockercomposels

然后确认:

  • 9000没有被其他服务占用。
  • 8090没有被其他网页服务占用。
  • 云服务器 存储空间足够容纳服务端数据和一份本地 Vault。
  • 当前 Obsidian Vault 已有独立备份或 NAS 快照。

🚨 ARM64 NAS 先不要直接启动 Perlite

截至 2026-07-17,Perlite 官方 Docker Hub 的latest/1.6.1只列出linux/amd64linux/arm/v7,没有列出linux/arm64。如果uname -m返回aarch64,先只部署 FNS 与 CLI;Perlite 需要自行构建或等待、选择经过验证的 ARM64 镜像。

可以用下面的命令再次核对镜像平台:

dockerbuildx imagetools inspect sec77/perlite:latest

3.2. 推荐的三阶段部署顺序


NAS 部署 Fast Note Sync 的三阶段流程

为什么不建议一次执行docker compose up -d

因为 CLI 必须先拿到管理员创建的 Vault 和 JWT Token。第一次同步时,也应该先做一次pull,确认目标目录正确,再开启常驻双向同步。

3.3. 建立目录并获取 CLI 源码

cd/home/caimingyang/obsidiangitclone https://github.com/Go1c/FastNodeSync-CLI.git fns-climkdir-pfast-note-sync/configmkdir-pfast-note-sync/storagemkdir-pfns-cli/configmkdir-pfns-cli/vaultmkdir-pperlite

如果fns-cli已经存在,不要重复克隆:

git-C/home/caimingyang/obsidian/fns-cli statusgit-C/home/caimingyang/obsidian/fns-cli pull --ff-only

⚠️ 生产环境建议固定 CLI 提交

FastNodeSync-CLI 是 FNS 主仓库列出的第三方客户端,目前没有正式 Release。测试稳定后记录git rev-parse HEAD,升级时先备份再切换提交,不要无条件跟随main

3.4. 放置 Compose 与 Nginx 配置

需要准备三个文件:

文件云服务器 目标位置
docker-compose.yml/home/caimingyang/obsidian/docker-compose.yml
fns-cli-config.yaml.example稍后复制为fns-cli/config/config.yaml
perlite.conf/home/caimingyang/obsidian/perlite/perlite.conf

本文附带的三个示例位于:

01-素材/部署示例/

文件放好后,先验证:

cd/home/caimingyang/obsidiandockercompose config

✅ Compose 通过的标准

命令能完整展开fast-note-sync-servicefns-cliperliteperlite_web四个服务,没有 YAML、缩进、网络或卷定义错误。

四、第一阶段:只启动 FNS 服务

4.1. 启动并检查日志

cd/home/caimingyang/obsidiandockercompose pull fast-note-sync-servicedockercompose up-dfast-note-sync-servicedockercomposepsfast-note-sync-servicedockercompose logs--tail=200fast-note-sync-service

浏览器打开:

http://云服务器_IP:9000

如果页面打不开,先在 云服务器 局域网内排查,不要第一时间做公网穿透:

curl-Ihttp://127.0.0.1:9000dockercompose logs--tail=200fast-note-sync-service

4.2. 初始化管理端

第一次进入管理端时:

  1. 注册第一个管理员账户。
  2. 登录管理端。
  3. 创建或确认要同步的 Vault。
  4. 记住 Vault 名称,后面三处必须完全一致。

这三处分别是:

  • FNS Web 管理端的 Vault 名称。
  • fns-cli/config/config.yaml中的server.vault
  • Obsidian Fast Note Sync 插件授权的 Vault。


05-FNS管理端初始化

4.3. 创建 CLI Token

进入管理端的 Token 管理页面,为 NAS 单独创建一个 Token。

按当前 FastNodeSync-CLI 文档,常驻读写同步可使用类似权限:

p:ws c:fns-cli* f:note_rw,file_rw,config_rw

如果暂时不启用.obsidian配置同步,可以先不授予config_rw,并保持:

sync_config:false

🚨 Token 就是知识库读写密码

不要把真实 Token 写进文章、截图、Git 仓库或群聊。为 云服务器 单独生成 Token,设置合理有效期;泄漏后立即吊销并重新生成。


06-FNS令牌创建

4.4. 初始化后关闭公开注册

官方配置支持:

user: register-is-enable:false

完成首个账户初始化后,检查挂载目录中的服务端config.yaml,关闭公开注册,再重启服务:

dockercompose restart fast-note-sync-servicedockercompose logs--tail=100fast-note-sync-service

如果只在可信局域网使用,也建议关闭;如果准备接入公网,更不能长期开放匿名注册。

五、第二阶段:配置 CLI 并首次只拉取

5.1. 编写 CLI 配置

创建:

/home/caimingyang/obsidian/fns-cli/config/config.yaml

内容如下:

server: api:"http://fast-note-sync-service:9000"token:"请替换为在 FNS Web 管理端生成的 JWT Token"vault:"知识库"sync: watch_path:"/app/vault"sync_notes:truesync_files:truesync_config:falseexclude_patterns: -".git/**"-".trash/**"-"*.tmp"-".fns_state.json"file_chunk_size:524288client: reconnect_max_retries:15reconnect_base_delay:3heartbeat_interval:30client_type:"fns-cli"logging: level:"INFO"file:""

需要替换的只有两个核心值:

  • token:刚才创建的 JWT Token。
  • vault:与 FNS 和 Obsidian 完全一致的 Vault 名称。

5.2. 保护配置文件

chmod600/home/caimingyang/obsidian/fns-cli/config/config.yaml

Compose 中把配置目录挂载为只读:

- ./fns-cli/config:/app/config:ro

但要明白:容器只读不等于宿主机安全。NAS 管理员、备份系统和有权限读取该目录的进程仍能看到 Token。

5.3. 构建 CLI 并首次只拉取

先构建,不启动常驻服务:

cd/home/caimingyang/obsidiandockercompose build fns-cli

第一次建议对一个空的fns-cli/vault执行pull

dockercompose run--rmfns-cli pull-c/app/config/config.yaml

为什么强调pull?因为它先把服务端内容落到 云服务器,避免一上来就监控一个目录状态不明确的本地 Vault 并向远端推送。

⚠️ 第一次同步前再确认一次

fns-cli/vault应该是空目录,或者是你已经确认与服务端完全一致的副本。不要拿一个来源不明、内容不同的旧 Vault 直接启动双向同步。

5.4. 检查第一次拉取结果

至少检查:

find/home/caimingyang/obsidian/fns-cli/vault-maxdepth2-typef|head-n50

应该重点确认:

  • 中文文件名是否正常。
  • Markdown 文件数量是否合理。
  • 图片和其他附件是否存在。
  • .fns_state.json是否生成。
  • Vault 根目录是否存在README.md

README.md是 Perlite 的首页。如果远端没有,建议先在 Obsidian 中创建,再同步下来,不要随便在 云服务器 端创建一个可能覆盖远端的同名文件。

✅ 首次拉取通过的标准

CLI 命令正常退出;云服务器 Vault 中出现预期的笔记和附件;抽查几个中文文件可以正常打开;没有认证、Vault 不存在或权限不足错误。

六、第三阶段:开启同步和网页发布

6.1. 启动常驻服务

确认首次拉取没有问题后再启动:

dockercompose up-dfns-cli perlite perlite_webdockercomposeps

检查日志:

dockercompose logs--tail=200fns-clidockercompose logs--tail=100perlitedockercompose logs--tail=100perlite_web

容器显示Up只是第一层。还要观察几分钟,确认fns-cli没有因为 Token、Vault 或网络问题反复重启。

6.2. 安装并授权 Obsidian 插件

在 Obsidian 中:

  1. 打开“设置 → 第三方插件 → 浏览”。
  2. 搜索并安装Fast Note Sync
  3. 启用插件。
  4. 回到 FNS Web 管理端。
  5. 打开“笔记仓库/Vault”页面。
  6. 点击“一键授权 Obsidian”;或者手动复制 API 配置到插件。

⚠️ 手机端一键唤起失败怎么办

先确认手机能访问 FNS 地址,再尝试手动粘贴配置。局域网地址、HTTPS 证书、反向代理和浏览器是否允许唤起 Obsidian,都会影响一键授权。


08-Obsidian一键授权

6.3. 打开 Perlite

浏览器访问:

http://云服务器_IP:8090

如果首页空白,优先检查:

  1. fns-cli/vault/README.md是否存在。
  2. NOTES_PATH是否等于容器内目录名Notes
  3. Perlite 是否挂载到/var/www/perlite/Notes:ro
  4. Nginx 配置中的fastcgi_pass是否为perlite:9000
  5. perlite_web是否通过volumes_from: perlite:ro读到相同文件。


09-Perlite网页效果

七、不要只看容器状态,要做三层验收

7.1. 验收清单

层级测试动作成功标准
服务层打开9000、检查 FNS 日志管理端可登录,日志无持续报错
同步层Obsidian 新建含图片的测试笔记云服务器 Vault 出现 Markdown 和图片
反向同步修改一篇专用测试笔记另一端收到修改,不产生重复文件
展示层打开8090Perlite 能显示目录、正文、图片和链接
持久化重启容器或 NAS账户、Token、Vault、页面仍存在
恢复层从备份恢复一份测试数据可以打开并核对,不只是“有备份文件”

7.2. 做一次端到端测试

建议在 Obsidian 创建:

FNS-部署验收.md

测试内容至少包含:

  • 中文文件名。
  • 一张图片。
  • 一个[[双向链接]]
  • 一个标签。
  • 一个代码块。

然后按顺序检查:

  1. 电脑端保存测试笔记。
  2. 手机端确认收到。
  3. 云服务器fns-cli/vault确认文件和图片出现。
  4. Perlite 确认页面能够打开。
  5. 在另一台 Obsidian 设备修改测试文字。
  6. 检查其他端是否同步更新。

7.3. 做一次重启测试

dockercompose restartdockercomposepsdockercompose logs--tail=100fast-note-sync-servicedockercompose logs--tail=100fns-cli

最后再重启一次 云服务器,确认:

  • FNS 账户和 Vault 没有丢失。
  • CLI 能根据.fns_state.json继续增量同步。
  • Perlite 仍然读取同一个 Vault。
  • 容器没有因为目录权限变化而启动失败。

八、同步、展示、备份要分开管理

8.1. 三条边界


同步、展示和备份的职责边界

这张图里最重要的不是三个组件,而是三句话:

  1. 同步会传播错误。
  2. 只读挂载不等于访问控制。
  3. 有备份文件不等于能够恢复。

8.2. 至少备份哪些目录

目录内容建议
fast-note-sync/storage默认数据库、附件和服务端数据定期快照;一致性备份时暂停写入或使用 云服务器 一致性快照
fast-note-sync/config服务端配置每次改配置后备份
fns-cli/configCLI 配置与 Token加密备份、严格限制权限
fns-cli/vault可直接阅读的 Obsidian 文件快照 + 离线副本 + 可选 Git 版本
docker-compose.ymlperlite.conf部署定义放入私有配置仓库,但不要提交真实 Token

🚨 不要只复制正在写入的数据库文件

FNS 默认可使用 SQLite。备份storage时,优先停止服务、使用 云服务器 的一致性快照,或者采用数据库支持的一致性备份方式。复制到一半的数据库不一定能恢复。

8.3. 更新与回滚

测试阶段可以使用latest,稳定运行后建议固定已验证版本或镜像摘要。

更新前:

dockercompose imagesgit-Cfns-cli rev-parse HEAD

然后:

  1. 记录当前镜像版本和 CLI commit。
  2. 创建storageconfigvault快照。
  3. 拉取新镜像或更新 CLI。
  4. 重新构建并启动。
  5. 完成同步、附件、Perlite 和重启验证。
dockercompose pull fast-note-sync-service perlite perlite_webdockercompose build --no-cache fns-clidockercompose up-ddockercomposeps

⚠️ 不要把“容器启动成功”当成“升级成功”

升级后必须再做一遍测试笔记、附件、Token 权限、Perlite 页面和重启验证。出现问题时,回到刚才记录的镜像版本、CLI commit 和数据快照。

8.4. 公网访问和 Token

最安全的顺序是:

  1. 先只在可信局域网跑通。
  2. 需要远程访问时优先使用 VPN。
  3. 确实需要公网时,再部署 HTTPS 反向代理和身份认证。

FNS 反向代理要支持 WebSocket;Perlite 前面要有访问控制。HIDE_FOLDERS只是页面展示过滤,不是权限系统。

🚨 不要把两个端口直接映射到公网

9000包含管理端和同步接口,8090默认也没有为你的私人知识库提供完整身份认证。至少使用 HTTPS、访问控制、强密码、独立 Token 和最小权限。

九、常见问题与避坑

9.1.services must be a mapping

❓ 为什么 Compose 一运行就报 YAML 错误?

原因通常是重复services:或列表缩进错误。先执行docker compose config,不要凭肉眼继续试。

9.2.unable to prepare context或找不到 Dockerfile

❓ 为什么 fns-cli 构建失败?

build.context必须指向 FastNodeSync-CLI 源码目录,该目录里要有Dockerfilerequirements.txtfns_cli/。本文使用context: ./fns-cli

9.3. CLI 找不到配置

❓ 为什么提示 /app/config/config.yaml 不存在?

检查宿主机是否真的存在fns-cli/config/config.yaml,再用docker compose config检查挂载。不要把服务端的config.yaml放进 CLI 配置目录。

9.4. Token 无效或权限不足

❓ 为什么日志出现 401、403 或 WebSocket 认证失败?

检查 Token 是否完整、是否过期、客户端类型是否匹配、权限是否包含需要同步的 note/file/config。不要在日志或截图中暴露 Token。

9.5. Vault 不存在或同步到错误目录

❓ 为什么 CLI 能连接但找不到笔记?

FNS 管理端、CLIserver.vault和 Obsidian 插件中的 Vault 名称必须完全一致,包括大小写和空格。

9.6. Perlite 首页空白或 404

❓ 为什么 8090 能打开,但没有正文?

依次检查README.mdNOTES_PATH=Notes/var/www/perlite/Notes:rofastcgi_pass perlite:9000volumes_from: perlite:ro

9.7.no matching manifest for linux/arm64

❌ Perlite 官方镜像与 ARM64 不匹配

当前官方镜像没有列出linux/arm64。先移除或暂停perliteperlite_web,只跑 FNS 与 CLI。不要用platform: linux/amd64强行模拟后就默认性能和稳定性没有问题。

9.8. 两台设备同时编辑发生覆盖

⚠️ CLI 上游说明并发修改以服务端最后写入为准

重要长文不要在多台离线设备上同时编辑。先用测试笔记模拟一次离线冲突,确认你能接受实际结果,再投入日常使用。

9.9. Perlite 隐藏目录后是不是就安全了

🚨 不是

HIDE_FOLDERS负责“页面不展示”,不是用户身份认证。最稳妥的做法是只给 Perlite 挂载专门的发布 Vault,或者在前面增加 VPN、Basic Auth、Authentik 等访问控制。

十、常用命令和最后结论

10.1. 常用命令

# 检查 Composedockercompose config# 查看状态dockercomposeps# 查看关键日志dockercompose logs-ffast-note-sync-servicedockercompose logs-ffns-cli# 首次只拉取dockercompose run--rmfns-cli pull-c/app/config/config.yaml# 启动常驻同步和发布dockercompose up-dfns-cli perlite perlite_web# 重启dockercompose restart# 查看镜像dockercompose images

10.2. 最后记住

这套方案真正稳定的关键,不是把四个容器一次性拉起来,而是守住顺序和边界:

先备份,再启动 FNS; 先创建 Vault 和 Token,再配置 CLI; 先只拉取并检查,再开启双向同步; 同步负责传播,Perlite 负责展示,独立备份负责兜底。

参考资料

  • Fast Note Sync Service
  • Fast Note Sync Obsidian 插件
  • FastNodeSync-CLI
  • Fast Note Sync Service Docker Hub
  • Perlite
  • Perlite Docker Setup
  • Perlite Docker Hub Tags

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

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

立即咨询