Obsidian WebDAV Sync

Obsidian WebDAV Sync

简介

Obsidian WebDAV Sync 是一款通用的双向 WebDAV 同步插件,专为 Obsidian 设计。它的诞生源于当前缺乏能够可靠且便捷地将仓库与 WebDAV 服务器同步的插件。它在可靠的双向同步、更优的性能以及摆脱厂商锁定方面优于现有解决方案:

🔄 可靠的双向同步

  • 本插件将你的仓库与 WebDAV 存储进行同步。
  • 它执行三方比较:远程状态、本地状态,以及上次同步时记录的本地和远程状态。
  • 随后遵循决策矩阵以实现最高精度和数据完整性,详见下文

🔀 自动同步与冲突处理

  • 插件支持以下自动触发的同步方式:
    • 启动同步:当 Obsidian 启动时触发同步。
    • 定时同步:周期性触发同步。
    • 实时同步:检测到更改时立即触发同步。
  • 插件支持以下冲突处理方法:
    • 智能合并
    • 最新者胜出
    • 使用远程版本
    • 使用本地版本
    • 跳过

🔐 客户端加密

  • 本插件支持在上传前对文件进行加密。
  • 它能防止未经授权的文件访问,并检测远程端意外的文件修改和移动。
  • 该加密流程基于更严格的威胁模型,相比类似解决方案(如 Remotely Save),实现了理论上更高的安全性、更快的性能和更小的插件体积,详见加密规范

极致性能

  • 大多数同步操作通过并行网络请求执行。
  • 实时同步默认使用缓存的远程状态,使其能在数秒内完成同步。
  • 体积比 Remotely Save 小 10 倍,启动加载时间快 8 倍

🧰 详细配置

  • 插件允许用户调整各种参数以适应不同的服务:
    • 最大并发 WebDAV 请求数:应对服务速率限制。
    • WebDAV 请求最小间隔时间:应对服务速率限制。
    • 跳过大文件:应对存储空间不足的情况。
    • 最大并发同步任务数:控制 CPU 和磁盘占用。
    • 最大并发吞吐量:控制内存使用并防止崩溃。

📦 生产级可扩展性

  • 流畅处理包含超过 3000 个文件的仓库。
  • 负载均衡和下载分块功能使插件能够一次性处理千兆字节级的数据。
  • 大文件下载支持断点续传。

🎨 优秀的用户界面与可观测性

  • 提供四种方式(模态框、状态栏、通知、日志)让你随时了解同步进度。
  • 文件更改以文件树形式呈现,支持细粒度的选择性同步。
  • 日志工具输出人类可读的 Markdown 文档。

又是另一个同步插件?

作为一名在多设备间工作的 Obsidian 用户,我亲身经历过同步困境:寻找一个既可靠、灵活,又不损害数据完整性的解决方案。在尝试了社区中几乎所有的同步插件后,我发现它们各自都存在令我日常工作流程受挫的权衡:

  • Remotely Save:功能全面,但存在维护停滞和 Bug 问题——例如已删除的文件会神秘重现(这正是我弃用它的主要原因)。
  • Syncthing Integration:提供了优秀的 P2P 同步体验,但要求所有设备必须同时在线。
  • Live Sync:虽然稳健,但代价是复杂的服务器搭建流程。
  • 基于 Git 的方案:在版本控制方面表现出色,但并不适合无缝的日常同步。

随后我发现了 Nutstore Sync —— 一款优秀的插件,但仅适用于坚果云。我想:为什么不把它做成通用的呢?于是我对其进行了 fork,并进行了大规模重构,以消除厂商锁定、提升性能并增强稳定性。由此诞生的作品便是 Obsidian WebDAV Sync

技术解析

文件处理

将 Obsidian 仓库同步到 WebDAV 服务器是一个典型的分布式协调问题,其中每个客户端都拥有自己的仓库副本和更改记录,且中间没有集中的解析器。目标是在客户端之间同步仓库,以实现最大的数据完整性。

为解决这一问题,本插件保留了本地和远程文件上次已知同步状态的记录。在同步期间,它会评估每个文件路径的三种状态(当前本地、当前远程、上次同步时记录的本地和远程),并据此决定同步操作:

✅ = 存在,❌ = 不存在,✏️ = 相较于记录已更改

情况本地文件远程文件同步记录操作
1⏭️ 跳过(已同步)
2✏️✏️⚠️ 解决冲突(应用策略)
3✏️⬇️ 拉取(下载远程版本)
4✏️⬆️ 推送(上传本地版本)
5🗑️ 删除本地(清理)
6🗑️ 删除远程(清理)
7✏️⬇️ 拉取(从远程恢复)
8✏️⬆️ 推送(恢复到远程)
9✅(与本地比较)📝 记录(捕获未记录的文件)
10✏️(与本地比较)⚠️ 解决冲突(首次同步)
11⬇️ 拉取(新远程文件)
12⬆️ 推送(新本地文件)
13🧹 清理记录(数据库清理)

加密

客户端加密是本插件中设计最严谨的部分。加密并非简单地使用密钥对文件的一部分进行编码,那种方式可能在几分钟内被攻击者破解。WebDAV Sync 中的真实加密过程涉及多层混淆和扩散,如下图所示。

Root File Key

File Content

File Key

Name Key

File Name

User Password

Master Key

Master Salt

Account Name

Server Endpoint

Remote Directory

File Size

File Path

16 Byte Random File Salt

File Key Salt

Chunk Count

在盐值中使用 WebDAV 服务器信息来混合用户密码,避免了 Rclone 式通用固定盐值带来的风险。通过选择 AES-GCM-SIV-256 作为文件路径加密的确定性算法,并将文件路径和大小直接编织到文件加密密钥中,该算法能够最大限度地验证下载文件的完整性,并检测恶意的文件移动和截断。

由此产生的加密流程在理论上比类似解决方案(如 Rclone Crypt)和竞争插件(如底层使用 Crypt 的 Remotely Save)更安全、更快,且更符合 Obsidian 原生体验

更多细节

本插件的技术层面还有更多值得深入探讨之处。

例如,在同步前比较四种状态意味着我们需要在每次同步开始时进行完整的 WebDAV、本地仓库和记录遍历,这对于大型仓库来说是不切实际的。为解决这一问题,引入了快速模式,它复用记录中的远程状态作为当前状态,从而避免每次同步都遍历整个 WebDAV。快速模式默认用于实时同步,建议在快速模式同步之前进行一次常规同步(由手动、周期性或启动触发)。

此外,存储所有文件的记录和内容(以比较并决定文件是否更改)需要大量且活跃的存储空间以确保保真度。本插件利用 IndexedDB 来存储记录并按需查询。

另外,为了控制内存使用并防止在下载大文件时崩溃,本插件采用了专门的负载均衡和下载分块机制。当文件大小超过用户配置的阈值时,插件会将文件分割成块并并行下载,且在每个块完成后立即保存到本地缓存。在最后阶段,插件对缓存进行排序并增量写入完整文件。这不仅确保在处理 GB 级文件时内存消耗保持在恒定的低水平,还使大文件下载完全支持断点续传。

安装与设置

由于本插件已上架 Obsidian 官方插件商店,你可以直接从 Obsidian 插件库中安装。

第一步:安装插件

  1. 打开 Obsidian 设置 → 社区插件
  2. 搜索并安装由 Hēsperus 开发的 WebDAV Sync
  3. 启用该插件

第二步:配置 WebDAV 连接

  1. 输入你的 WebDAV 服务器 URL
  2. 提供账户凭据
  3. 点击 检查连接 以验证
  4. 选择你的远程目录
  5. 发起首次同步

在首次同步前,请务必备份重要笔记。虽然本插件能稳健地处理文件存在性解析,但在初次设置时拥有备份能让你更安心。

许可证

Obsidian WebDAV Sync 采用 AGPL-3.0 许可证

最后更新:

所有内容依据 CC BY-SA 4.0 许可证授权。