hayatosc
Posts

Obsidianの同期にlivesync-workersを使い始めた

Obsidian Self-Hosted LiveSyncのCloudflare Workers実装の話

4 min read

私は長期間蓄積するノートをObsidianで管理している。最近はノート同士の関係性をAIに整理・構造化させることで、知識の理解を深める使い方が定着してきた。

ところでObsidianといえば、特に課題となるのが「同期どうするのか問題」である。

公式が用意している Obsidian Sync というサービスは最低でも月額4ドルかかるため、できれば避けたい。しかし、それ以外の方法(GoogleドライブやGitによる同期など)はモバイルでの制約や同期衝突の扱いなど、体験としてあまり良くないのが長年のネックであった。

Self-Hosted LiveSync

その点、コミュニティプラグインの Self-Hosted LiveSync は非常に良い。

GitHub - vrtmrz/obsidian-livesync Contribute to vrtmrz/obsidian-livesync development by creating an account on GitHub. github.com

同期スピードはほぼリアルタイムで申し分なく、端末間の競合でデータが破壊されるようなこともめったに起きない。本家Obsidian Syncに近い使用感を得られる素晴らしいプラグインである。

弱点

そんなSelf-Hosted LiveSyncの弱点は、同期サーバーとしてCouchDBを必要とする点である。これはかなりややこしい。

昔はFly.ioに無料でデプロイすることができたが、今はその無料枠も消滅している。新しく始めるには自宅のPCやRaspberry Piなどを使って常時起動サーバーを立てなくてはならない。ただMarkdownファイルを共有したいだけなのに、個人サーバーの保守まで抱え込むのは負担が大きすぎる。

livesync-workersという選択肢

そんな中、Xを見ていて気づいたのが @odiak_ さんのlivesync-workersだ。

GitHub - odiak/livesync-workers: Self-hosted LiveSync-compatible backend for Obsidian with search and MCP, on Cloudflare Workers Self-hosted LiveSync-compatible backend for Obsidian with search and MCP, on Cloudflare Workers - odiak/livesync-workers github.com

なんとSelf-Hosted LiveSyncのプロトコルに合わせたCloudflare Workers実装である。自分もObsidianの共有に使えるプロジェクトを考えて自前実装していたのだが、既存のプラグイン資産に乗れるという点で筋がいいと思った。

既存の仕組みをそのまま活かせる点に惹かれ、早速導入することにした。実際には自分の用途向けにフォークしたバージョンを使用している。

GitHub - hayatosc/livesync-workers: Self-hosted LiveSync-compatible backend for Obsidian with search and MCP, on Cloudflare Workers Self-hosted LiveSync-compatible backend for Obsidian with search and MCP, on Cloudflare Workers - hayatosc/livesync-workers github.com

フォーク元ではDurable Objects上のSQLiteに本文のすべてを保存する仕様だったため、100MBという容量制限があった。これを超過することは当面なさそうだが、今後Vaultが大きくなったり画像も保存したかったりしたため、ファイル本文や添付データの実体をR2に直接保存するようにした。

あと、元のベクトル検索を外した代わりにBM25による全文検索を入れてみた。BM25は形態素の分割が必要になるが、最近のJavaScript環境には Intl.Segmenter というAPIが標準であるらしい。専用の形態素解析ツールと比べると精度は劣るものの、検索結果をAIにコンテキストとして渡す用途であれば十分に実用的だろう。

Intl.Segmenter - JavaScript | MDN Intl.Segmenter オブジェクトは、ロケールに応じてテキストを区切ることができ、文字列から意味のある項目(書記素、単語、文)を取得することができます。 developer.mozilla.org Intl.Segmenterはどうやって単語分割しているのか zenn.dev

おわりに

とりあえず使ってみているが、時々エラーが出て失敗したりするがそこそこ上手く動いているようである。

サーバーレスなLiveSync環境として、しばらくこれで生活してみる。