引言

Obsidian 是一款优秀的本地知识库工具,但是其没有免费的多端同步服务,其他人我不知道,这个问题反正很困扰本人。我主要是在教室主要使用平板编辑,在寝室就换为电脑了,所以有频繁的多端同步需求。

奈何官方同步服务收费较高,而第三方网盘(iCloud、百度云、OneDrive 等)存在隐私顾虑和速度限制。所以我选择自建同步方案,但这么搞往往需要处理协议兼容性、权限配置等等细节。于是在寒假折腾一天,这里就总结一下,旨在为有类似需求的读者提供一份兼顾专业性与可操作性的参考。

本文记录的是我从最初尝试 Nextcloud+WebDAV 到最终采用腾讯云 COS(对象存储)实现电脑、手机、平板三端稳定同步的全过程,尝试深入剖析各阶段遇到的技术问题及其原理。

本文部分使用 AI 辅助编写。


WebDAV 方案的尝试与失败

初始架构:Nextcloud + WebDAV

我最初利用服务器,通过 Docker (服务器还有其他东西,求放心搞了一个隔离)部署了 Nextcloud(版本 23),并启用其 WebDAV 服务。在电脑端 Obsidian 中安装 Remotely Save 插件,配置 WebDAV 连接后,同步功能正常,文件可双向传输。这就验证了自建同步的可行性。

安卓端的异常现象

但是,当在安卓手机和平板上进行同样配置时,问题出现了:同步状态极不稳定,频繁返回 401 Unauthorized 错误,连接测试时而成功,时而失败,无固定规律。偶尔成功同步一次后,再次尝试即失败。设备重启后短暂恢复,随后再次报错。不同安卓设备表现一致,排除了个别设备故障。

排查过程:

针对上述现象,我和 AI 聊了聊,做了排查:

  1. 凭证验证:重置 Nextcloud 账户密码,重新输入插件配置,问题依旧。
  2. 域名与信任:在 Nextcloud 的 config.php 中添加了手机访问的 IP 和域名,避免请求被拒绝。
  3. 网络环境:切换 Wi-Fi、4 G/5 G,甚至使用手机热点连接,未能改善。
  4. 服务:使用手机浏览器直接访问 Nextcloud 的 WebDAV 地址,输入凭证后可以正常浏览目录,说明服务本身是正常的,且网络无阻断。

根本原因分析

走投无路,于是求助伟大的 deepseek ,他查阅 Remotely Save 插件开发者文档及相关技术讨论后,发现了问题根源:安卓系统底层对 WebDAV 协议的非标准 HTTP 方法支持存在缺陷

他说:

“WebDAV(Web-based Distributed Authoring and Versioning)在标准 HTTP 方法(GET、POST、PUT 等)基础上扩展了 PROPFIND、PROPPATCH、MKCOL、COPY、MOVE 等方法,用于实现目录列表、属性操作等功能。这些扩展方法并非所有 HTTP 客户端库都完美支持。”

“安卓端 Obsidian 运行在 Capacitor 容器中,其网络请求依赖于系统提供的 requestUrl API。该 API 对 WebDAV 扩展方法的实现不够稳定,某些请求可能被系统拦截、修改或直接拒绝,导致服务端收到畸形请求或根本无法到达。这种现象在 Android 10 及以上版本中尤为明显,且与具体设备或系统版本相关,因此表现出随机性故障。”

一知半解,反正就是不行,只好掉头。

结论:

WebDAV 协议在安卓移动端存在天然的兼容性风险(问就是神秘代码),并非配置错误,我无力可以解决。因此,不得不寻找一种使用标准 HTTP 方法、且移动端支持良好的同步协议。DS 说 S 3 协议恰好满足这一要求。


转向 S 3 协议与腾讯云 COS

S 3 协议的说明

S 3(Simple Storage Service)协议最初由亚马逊提出,现已成为对象存储的事实标准。其主要特点包括:

  • 使用标准 HTTP 方法:仅依赖 GET、PUT、DELETE、HEAD 等标准动词,无需扩展方法,安卓系统网络层无任何阻碍。
  • 广泛兼容:几乎所有云厂商(腾讯云、阿里云、AWS 等)及开源存储系统(MinIO、Ceph)均支持 S 3 API,生态成熟。
  • 安全性:支持基于签名的请求认证(AWS Signature V 4),可有效防止请求篡改。

Remotely Save 插件原生支持 S 3 兼容协议,为迁移提供了便利。

对象存储的简介

对象存储可以理解为一种云端的大容量键值存储系统。每个文件(对象)都有一个唯一的键(即文件路径),通过 HTTP API 进行上传、下载和删除。与传统文件系统(自己买的云盘)不同,对象存储没有目录层级的概念(路径只是键的一部分),但客户端可以通过模拟前缀来组织文件。它具备高可用、高持久性、几乎无限扩展的优点,且按实际使用量付费,非常适合个人笔记这类小规模数据。

腾讯云 COS 配置步骤:

创建存储桶

  • 登录腾讯云控制台,进入对象存储服务。
  • 点击“创建存储桶”,填写以下信息:
    • 名称:全局唯一,例如 obsidian-1250000000
    • 所属地域:选择与自己最近的数据中心(如广州 ap-guangzhou),以降低访问延迟。
    • 访问权限:选择私有读写。这是安全底线,严禁选择公有读写,否则数据可能泄露。(还会花钱)
    • 其他选项保持默认,点击“确定”。

2.3.2 创建子账户与密钥(最小权限原则)

为保障主账户安全,应创建专用子账户并授予最小必要权限:

  1. 进入“访问管理” → “用户” → “新建用户” → “自定义创建”。
  2. 勾选“编程访问”,以便生成密钥。
  3. 在权限设置阶段跳过(后续单独授权)。
  4. 用户创建成功后,务必保存弹出的 SecretId 和 SecretKey,此界面仅出现一次。
  5. 返回存储桶列表,进入刚创建的桶,选择“权限管理” → “存储桶访问权限” → “添加用户”。
    • 用户类型:子账号,选择刚创建的账户。
    • 权限勾选:数据读取、数据写入、数据读取(列表)。这三项允许插件列出文件、下载和上传。
  6. 保存后等待 1-2 分钟使权限生效。

CORS 规则配置(移动端访问关键)

介绍:跨域资源共享(CORS)是一种安全机制,用于限制 Web 应用向不同源发送请求。Obsidian 移动端运行在 Capacitor 容器内,其请求的 Origin 与普通浏览器不同,必须显式允许才能通过 COS 网关。

在存储桶的“安全管理” → “跨域访问 CORS”中,添加如下规则:

  • Origin:逐行填写以下三个值
    achpatppt:ap/c:/i/otblsroi:cd/ai/lalhnoo.csmatdlhost
  • Methods:全选 GET、PUT、POST、DELETE、HEAD。
  • Allow-Headers:填写 *,允许所有请求头。
  • Expose-Headers:填写 ETag,用于文件校验。
  • Max-Age:设置为 0,表示不缓存预检结果。

DS 的解释:移动端 Obsidian 发起的请求,其 Origin 头为上述三个之一。COS 接收到请求后会检查该 Origin 是否在 CORS 规则中,若不在则拒绝。因此必须将这些 Origin 加入白名单。

开启版本控制(数据恢复保障)

这一步可选,不是必要,因为毕竟是多端存储,而且我自己没有设置自动同步,出问题了还有其他设备。

在存储桶的“数据管理” → “版本控制”中,点击开启。开启后,对文件的每次修改、删除都会生成一个新版本,并保留历史版本(默认 30 天)。当误删文件时,可通过控制台列出历史版本并恢复,所有同步设备将自动拉取恢复的文件。

Obsidian 端配置

  1. 安装并启用 Remotely Save 插件。
  2. 在插件设置中,选择远程服务为“S 3 兼容”。
  3. 填写以下参数:
    • 服务地址https://cos.<地域>.myqcloud.com(例如 https://cos.ap-guangzhou.myqcloud.com
    • 区域:地域代码,如 ap-guangzhou
    • Access Key ID:子账户的 SecretId
    • Secret Access Key:子账户的 SecretKey
    • 存储桶名称:存储桶名称(如 obsidian-1250000000
  4. 点击“检查连接”,若显示成功,则配置无误。

针对移动端性能优化,建议在“高级”设置中进行以下调整:

  • 并发数:从默认 5 改为 1。移动设备内存有限,高并发易导致 Obsidian 卡顿或闪退。
  • 跳过大文件:开启,并设置阈值如 10 MB。笔记库中若包含 PDF、图片等大文件,可避免同步时阻塞,这些文件可单独管理。(同步出问题主要原因)
  • 同步隐藏文件和文件夹:开启。
  • 包含. Obsidian 配置文件夹:可选开启。此选项确保插件的配置、主题等元数据跨设备同步,使新设备开箱即用。但是不同端可能会有 bug,这在插件里面作者自己也强调说明了。

要 AI 总结了一下实践中的典型问题与解决方案:

安卓端 401 Unauthorized(CORS 缺失)

现象:手机检查连接时报 401,但电脑端正常。
原因:CORS 规则中未包含 app://obsidian.mdcapacitor://localhost
解决:按 2.3.3 节配置完整 CORS 规则,等待一分钟生效。

403 Forbidden(权限不足)

现象:某天手机同步突然失败,返回 403。
原因:子账户权限仅授予了“读取”,缺少“写入”或“列表”权限。
解决:在存储桶权限管理中补充相应权限,并等待生效。

流量费用预警

现象:月初收到腾讯云欠费 1 分钱短信,经查为外网下行流量费用。
数据分析:统计一周同步流量,平均每日约 19.71 MB,年累计约 7.2 GB。按腾讯云标准存储外网下行流量单价 0.5 元/GB 计算,年费用约 3.6 元。
对策:预充值 10 元,由系统自动抵扣。不建议购买流量包,个人使用场景下按量付费更经济。

误删文件的恢复

现象:在手机上删除一篇笔记,同步后其他设备也同时删除。
解决方案:利用已开启的版本控制功能:

  1. 登录腾讯云 COS 控制台。
  2. 进入存储桶,点击右上角“列出历史版本”。
  3. 找到被删除的文件(显示有“删除标记”),选中并点击“恢复”。
  4. 恢复后,所有设备在下次同步时会自动拉取文件。

首次同步卡顿/闪退(移动端)

现象:新设备首次同步数千个文件时,Obsidian 无响应。
原因:并发数过高(默认 5)导致内存不足;同时存在大文件拖慢进程。
解决:临时将并发数设为 1,并开启“跳过大文件”(阈值 10 MB)。同步完成后再恢复并发数。

配置不同步(插件/主题)

现象:电脑端安装新插件后,手机端未出现。
原因.obsidian 文件夹为隐藏目录,默认不同步。
解决:在插件设置中开启“同步隐藏文件和文件夹”及“包含. Obsidian 配置文件夹”。


扩展应用:同一存储桶内多库隔离

若需在同一存储桶中管理多个 Obsidian 库(如工作库、个人库),可利用 Remotely Save 插件的“远端前缀路径”功能实现逻辑隔离。

实现方法

  1. 对于库 A,在插件设置中将“远端前缀路径”设为 work
  2. 对于库 B,设为 life
  3. 首次同步时,插件会自动在存储桶根目录下创建对应前缀的文件夹,后续文件将存储于各自前缀下。

此方式无需新建存储桶,不增加额外费用,且版本控制、CORS 等全局配置依然有效。这里只是一个配置的选择而已,但建议第一次配置时就安排好具体文件夹,而不是放在根目录(即什么都不填)。


最后:总结与学习收获

通过上述方案,几乎可以成功搭建一套稳定运行的 Obsidian 三端同步系统,总费用不足 5 元/年。更重要的是,在实践过程中可以深入理解了以下技术概念:

  • 对象存储原理:掌握其按量付费、高可用的特性,为未来搭建图床、备份服务器等应用打下基础。
  • 云服务权限管理:领会最小权限原则,学会通过子账户和策略隔离风险。
  • CORS 机制:明白跨域请求的约束与配置方法,不仅适用于 COS,也适用于任何 Web API 开发。
  • 版本控制与数据恢复:认识到数据保护的重要性,学会利用云服务自带功能应对误操作。

这些技能具有广泛的可迁移性,无论是继续探索其他云服务,还是开发个人项目,我们应该都能从中受益。