展示HN:YAOS – 一键部署的Obsidian实时同步引擎
嘿,HN,
我是一个重度使用 Obsidian 的用户。
最近,我对两种常见的同步方案感到厌倦:
1. 基于文件的同步(如 iCloud、Dropbox、Syncthing),需要等待更改传播,或者会出现“冲突副本”。
2. 自托管的设置(如 CouchDB),需要操作虚拟机和容器化数据库来同步 Markdown。
因此,我构建了 *YAOS*:一个以本地优先、实时同步为特点的 Obsidian 引擎。
自托管的开源软件应该提供更好的用户体验。
您可以一键将后端部署到自己的 Cloudflare 账户中。它适合 Cloudflare 的免费套餐(正常个人使用费用为 $0/月),并且完全不需要终端交互、SSH 或环境文件。
您现在可以试用: [https://github.com/kavinsood/yaos](https://github.com/kavinsood/yaos)
*它的工作原理:*
- 文本同步使用 Yjs CRDT。它实时同步按键和光标,而不是将保管库视为一堆待后续处理的文件。
- 每个保管库映射到一个 Cloudflare Durable Object,为您提供低延迟的单线程协调器。
- 后端在 Durable Object 的 SQLite 存储之上使用分块的 Checkpoint + Delta-Journal MVCC 存储引擎。
- 附件通过 R2 单独同步(这不是必需的——文本同步在没有它的情况下也能正常工作)。
这个项目最困难的部分是将 Obsidian 的同步 UI 和嘈杂的操作系统文件监视器与内存中的 CRDT 图进行桥接。我必须构建一个尾部快照排水系统,将快速的 IO 峰值(如执行全局查找和替换)合并为原子 CRDT 事务,以防止无限写入循环。
当前设计为每个保管库保持一个单一的 CRDT。这对于普通的个人笔记非常好,但有一个硬性的内存上限(约 50MB 的原始文本)。我选择了这个权衡,因为我更关心快速、可靠的实时使用体验,而不是无限的企业规模。
我还在 GitHub 上写了关于一些棘手部分的工程笔记(例如处理离线文件夹重命名冲突而不复活死文件)。
过去三周,我进行了严格的质量保证测试,以增强移动重连、IndexedDB 配额失败和离线分脑目录重命名的稳定性。
我非常希望能得到关于架构、代码或我所做权衡的反馈。我会在讨论中待着,回答问题!
查看原文
Hey HN,<p>I'm a heavy Obsidian user.<p>I recently got tired of the two usual sync tradeoffs:<p>1. File-based sync (iCloud/Dropbox/Syncthing) that leaves you waiting for changes to propagate, or hands you a "conflicted copy."
2. Self-hosted setups (like CouchDB) that need touching VMs and dockerized databases to sync markdown.<p>So I built <i>YAOS</i>: a local-first, real-time sync engine for Obsidian.<p>Self-hosting OSS should have better UX.<p>You can deploy the backend to your own Cloudflare account in one click. It fits comfortably in Cloudflare's free tier (costing $0/month for normal personal use), and requires absolutely no terminal interaction, no SSH, and no env files.<p>You can try it out right now: <a href="https://github.com/kavinsood/yaos" rel="nofollow">https://github.com/kavinsood/yaos</a><p><i>How it works under the hood:</i><p>- Text sync uses Yjs CRDTs. It syncs real-time keystrokes and cursors rather than treating the vault as a pile of files to push around later.
- Each vault maps to a Cloudflare Durable Object, giving you a low-latency, single-threaded coordinator at the edge.
- The backend uses a chunked Checkpoint + Delta-Journal MVCC storage engine on top of the DO's SQLite storage.
- Attachments sync separately via R2 (which is optional—text sync works fine without it).<p>The hardest part of this project was bridging Obsidian's synchronous UI and noisy OS file-watchers with the in-memory CRDT graph. I had to build a trailing-edge snapshot drain that coalesces rapid-fire IO bursts (like running a find-and-replace-all) into atomic CRDT transactions to prevent infinite write-loops.<p>The current design keeps a monolithic CRDT per vault. This is great for normal personal notes, but has a hard memory ceiling (~50MB of raw text). I chose this tradeoff because I cared more about fast, boringly reliable real-time ergonomics than unbounded enterprise scale.<p>I also wrote up engineering notes on the tricky parts (like handling offline folder rename collisions without resurrecting dead files) on GitHub.<p>I've spent the last three weeks doing brutal QA passes to harden mobile reconnects, IndexedDB quota failures, and offline split-brain directory renames.<p>I'd love feedback on the architecture, the code, or the trade-offs I made. I'll be hanging out in the thread to answer questions!