Skip to content
Go back

Self-hosted LiveSyncとTailscaleで外出先でも快適なObsidianのリアルタイム同期

あらすじ

という内容。

alt text

左がMacOS、右がAndroid(scrcpyで映している)

背景

Obsidianを端末間で同期する方法に迷っていた。というのも、普段はMacbookとAndroidスマホをメインで使用しており、これらのOS間で同期する手段が限られているからだ。

Obsidian公式が提供しているObsidian Syncを利用するのが最も楽だが、最安のプランでも$4/月と出費がちくちくと痛い。コーヒー1杯我慢すればいいのではと思うが、コーヒーを1杯我慢することはとても難しい。

Obsidianは親切にも公式(Obsidian Sync)以外の方法で同期する方法をガイドしてくれていて、MacOS・Android間の同期であればGoogle Driveを使う方法があった。

Sync your notes across devices

この方法はAndroid側にGoogle Driveをローカルフォルダとして利用できる3rd party appを導入して設定するというものではあるが、この方法は個人的に好みではなかった。

更に良い同期方法はないかと暗中模索していたところ、 Obsidian Self-hosted LiveSync という素晴らしいコミュニティプラグインを発見。どういうプラグインかというと、自分で用意したCouchDBというNoSQLのデータベースを使用して1 、端末間で(ほぼ)リアルタイムで同期するというもの。エンドツーエンド暗号化(E2EE)がサポートされていたり、編集履歴が管理できるのも良い。

graph LR
    subgraph "クライアント (各デバイス)"
        PC["fa:fa-desktop Mac / Windows"]
        Phone["fa:fa-mobile-alt iOS / Android"]
    end

    subgraph 自宅サーバなど
        DB[("Self-hosted Server
        **CouchDB(NoSQL)**
        MinIO(Object Storage)")]
    end

    %% 同期の流れ
    PC <-- 同期 --> DB
    Phone <-- 同期 --> DB

    %% スタイル
    style DB fill:#f2f2f2,stroke:#333,stroke-width:2px

公式ドキュメントではクラウド環境(fly.io)にCouchDBのインスタンスを作る方法のほか、ローカル環境にDockerでDBを構築する方法も案内されている。これならデータが宅内ネットワークから出なくて良いし、前述のE2EEもあるためDBサーバーが侵害されても、自宅に空き巣が入ったとしても、多少は安心。

ここで問題となるのが、データが宅内にあるので外出時にアクセスできない、ということ。これを簡単に解決するのが、Tailscaleである。

Tailscaleは簡単に言うと、NAT越えとWireGuard(VPNプロトコル)によりデバイス同士が直接P2Pで暗号化通信できる環境を構築するサービス。Tailscale自体は実際の通信データを中継せず、各デバイスの認証や鍵交換を調整することでその直接接続の確立を仲介する役割を担っている。

https://tailscale.com/blog/how-tailscale-works

Obsidian Self-hosted LiveSyncとTailscaleを組み合わせることで、外出先でも気軽に自宅に構築したCouchDBに同期でき、これはほぼObsidian Syncである。

ただ、Obsidian Syncとは異なり、停電などが発生すると同期できなったり、火災などで消滅した場合にデータベースも消失するという欠点がある。思い返すと自宅は最低でも年に1度は停電している気がするが、一時的に同期できなくてもメモ書きに支障はないので、大きな欠点だとは考えていない。

ここからは、自宅のラズパイサーバーに環境構築したときの記録。

用意するもの

サーバーの下準備

前提として、以下の2つは完了しているものとする。

CouchDBの準備

まずはCouchDBをセットアップする。ドキュメント通りDocker Imageを使うのが気軽で良い。

CouchDBの起動

docker composeで簡単に起動できる。redditの素晴らしいGuideを参考に以下のdocker-compose.ymlを使用している。

services:
  couchdb-obsidian-livesync:
    image: couchdb:3.3.3
    container_name: obsidian-livesync
    restart: unless-stopped

    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Asia/Tokyo
      - COUCHDB_USER=obsidian_user
      - COUCHDB_PASSWORD=must_be_changed

    volumes:
      - ./data:/opt/couchdb/data
      - ./etc:/opt/couchdb/etc/local.d

    ports:
      - "5984:5984"

あとはこれを適当なディレクトリに配置し、docker compose up -d する。

CouchDBのセットアップ

起動後は http://${hostname}:5984/_utils から管理画面にアクセスしてGUIベースでポチポチと設定できるが、REST API経由で一気に設定するshell scriptが用意されている。

(執筆時点のmain branch) https://github.com/vrtmrz/obsidian-livesync/blob/18d1ce8ec892f6955b48953a2499a2fb7d088d64/utils/couchdb/couchdb-init.sh

export hostname=localhost:5984
export username=obsidian_user
export password=must_be_changed

curl https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/refs/heads/main/utils/couchdb/couchdb-init.sh -o couchdb-init.sh

cat couchdb-init.sh # これも実行前に改ざんされていないか確認しよう

bash couchdb-init.sh

CouchDBをhttpsでserveする

モバイルデバイス(iOS, Android)から使用する場合、CouchDBのURLはhttpsでないといけない。幸いなことに、TailscaleにはLet’s Encryptで証明書を発行し、httpsでserveする機能も備わっており、コマンド一つで簡単にhttps化することができる。

⚠️注意: 証明書が発行されるため、ホスト名がインターネットに公開されることに注意。あくまでホスト名の公開だけで、インターネットからDBにアクセスすることはできない。

tailscale serve -bg 5984

これで、CouchDBにhttpsでアクセス可能になる。このときのURLはシンプルに https://${machine_name}.${tailscale_name}.ts.net/ となる。

同期をするためのデーターの受け皿が準備できたら、次は同期を行うクライアント側の設定に進む。

Self-hosted LiveSyncの設定

まずはじめに、現在のVaultをバックアップしておく。プラグインの導入中にデータが吹っ飛ぶということは往々にして起こり得る。Vaultのフォルダごとどこかにコピーしておくのがいい。

バックアップしたら、早速Pluginをインストールし設定をする。 設定は、画面をポチポチと進めることもできるが、Setup URIというObsidian URIを利用した簡単なセットアップ方法も用意されている。CouchDBの接続先やE2EEのパスフレーズなどの設定値が含まれたURIをクリックすることで、PluginのURI Handlerが設定値を解析して自動で設定してくれる。

では、どうやってそのURIを生成するかというと、これも生成用のscriptが用意されている。

https://github.com/vrtmrz/obsidian-livesync/blob/18d1ce8ec892f6955b48953a2499a2fb7d088d64/utils/flyio/generate_setupuri.ts (Commit IDは執筆時点のmain branch)

これは、次のようにして使用することができる。

export hostname=https://tiles-photograph-routine-groundwater.trycloudflare.com #Point to your vault
export database=obsidiannotes #Please change as you like
export passphrase=dfsapkdjaskdjasdas #Please change as you like
export username=johndoe
export password=abc123
deno run -A https://raw.githubusercontent.com/vrtmrz/obsidian-livesync/main/utils/flyio/generate_setupuri.ts

denoがインストールされていない場合は、インストールをしておく。

参考: https://docs.deno.com/runtime/getting_started/installation/

# MacOS
brew install deno
# npm
npm install -g deno
# General
curl -fsSL https://deno.land/install.sh | sh

これを実行すると、次のように設定値が暗号化された状態で埋め込まれたURIとそのパスフレーズが出力される。

Your passphrase of Setup-URI is:  snowy-firefly
This passphrase is never shown again, so please note it in a safe place.
obsidian://setuplivesync?settings=%252b30f41c97e02d5dadb520a601000000388ec66763bc2c9967ae711c4c509dddWnjaPo8VVkioQBoTmj%2FPDkcgOk0mZlWfV6JFCJHaQ9nGudfJLC1Ls1hbYzkzgnbb%2FhijWIHMBfA3elooSvdSoqy8xp2duW2p%2FqJJbMmQWASIYMa1R4x0GR0P4T71%2Btc5VUaLf3EtLqcNOR4r6k9dCa9SGRGLLdBhWKSGydb6Lpkq9VtWkYjpTPAKbkHD%2FGsQKiwGtN28O4bBsOXzmSwTxymDR1M9bnJI23wQXB1CWzqdoqkxVMz9UJJRUjfC546Z7LW2FUCE6orSjjksJgEE5WEmQ55%2BKiPpnpdp0dc0lMTp5Ml7fzpfEyjxtB9G%2FvaqtI6TlgrX4%2BKGE62%2FwoLHDlwrwjjhiB2kCTWjMMfCwt2wNlsHqPCL0SoEGhe85ofAg6dXhMtljcsK7kAznMPZxuU3jPiuZHErdTImfcWpkEeen%2BtTg1pe3ThQbWK1LqwnL6F7PMya0dBBQCvrtr2THYL%2FLcfGUAXA5MllEcRkfAPKmoJnCwK%2BDTADTB2qnKJoB7R%2FF0gojUK9TS21u4UYW%2Bq8uRtsXPITU%2B7yJ7ufWEJLHufzJ5IU%2FOl8AdNiBUvyM59jcs%2FX3NHYXsyN2oXaFjoEag3wkj5CgXKzddPy%2BGxVY2iDyY4dFcCDEp3xjrdimpK2ev7PPYIY%2FrgM%2BDOIvgl17Qc1qfFev3jhNLXy%2F508LgA8co8%2BaqoZUqRNzlc38QsAPr2KcskoX3ZW3ZVlq0bk4azND4xdZnNfWkq4Pgkdb7PWOKbJsod8LYwjUegRqLbkMiVsT6PJPEwCBVlwn6Cy523pX6C%2FwRm%2BXq%2F0Hsa%2Fg%2B7ypvQMTi0xvHt%2BFepPpChDNBYDgvV11IE%2F8Q7N4Tj8m0gujPYBJdKh28yvW7d98S10GGc476UAkJ4YB3Sx5u34%2Bjj0DWaGohZr%2FUm6lg%3D%3D

このSetup URIをクリックするとObsidianが開かれ、パスフレーズを入力することでURI設定値が自動で入力される。

alt text

パスフレーズ入力画面

alt text

入力された設定画面

あるいは、Pluginの設定画面からSetup URIを直接入力することもできる。

alt text alt text

あとは同様にパスフレーズを入力して、設定が完了する。

二台目以降のセットアップ

設定した一台目の端末から、その設定を他の端末に流し込めるSettings QR Codeというものが生成できる。それをモバイルデバイスのカメラで読み取ると、設定が完了する。Setup URIとの違いは、暗号化されていないということと、URIのエンコーディング形式が若干異なるということくらい。気になる場合は、Setup URIを自力でQRコード化することで、URIパスフレーズで暗号化したまま転送できる。

alt text

このQRには接続先の認証情報だけでなくE2EEのパスフレーズも含まれているため、他人には見られないように気をつける。QRの中身はObsidian URIで、Setup URIと同じ仕組みでObsidianに処理される。

obsidian://setuplivesync?settingsQR=V0fW1qhttps%3A%2F%2Ftiles-photograph-routine-groundwater.trycloudflare.comV7johndoeV6abc123VdobsidiannotesA1kA26ytVidfsapkdjaskdjasdastfa250a250ttffVg6adab30f74d2d32bffa250ta10ffffA28ca250A22sA22sV8xxhash64fV0V0V0V4autoV0fA1aA2sgA1afftfa11fffttfA31jkfffttfV3deftfa15a260a250fVa.gitignoreV0V0ffffV0W46%25%24l4oiZMdNqEVw%2BN0ggD%2F7PAuMqBBWzw8DPwNKlzwOQzFrAenuYxtnZ1HWmT925e7m2AnsYzzo%2FRHEf74z926bYd4kWoVmcZ9hnpXPRLoXBfHT2MkDoErQF%2FBdsGkbPkcZM9zG4GTitu2Wa7q5uio%3DWk6%25%24l4oiZMdNqEVw%2BN0ggD%2F7PAuMqBBWzw8DPwNKlzwOQzHALQRXyFfQTXJccQ2r0PTp1qQwoownyGp6An26wvjITPx07H53aEl0%2BXwwyQL6D5xmcFSpt1TGKGaqWyavMxLxgG%2F90FrRb%2F0XQJmjg%2BdA8EvTc8JUD78WSlR9d3th0UuFEbc%2Bcc%2BDPlpkZeg%2Fo1XiLQid9fG0NCVUyLrThPunK9jTX9MmCveW5uFD6uPBehvEMOJikfYGUPnx%2FUIlEvPW3yKHWxCMkAM00yf5QqBhbGcdmf5u6rridpxVwaxt7hAtTuSR8TPKjxI0gmsd6vrQIE7QWPMoTHimMB19zK%2Fv5izWaMmlwKGwHKfiYjQYAy5HYPBUxveX8z3lI5IsXLUISPiQRUZSyD5CzUMkNfYYf6ZY4OvbbR8kk0trAIADi6BqkXGbZObzrVQmb7QbmyBWIr1mnPd4fZqspiQHceJST%2FLrO9qVwpxJ1JBf8rApPB2vfGn2yplfdIfWJTcQLo%2BV54RS2WGkx7fMdyJyMq9ASGziyMFg45nXPiP6CKub7wXmzN0cJrmsr8gwnaowu4Wy7SGSdfDLaSvA7hozxLqDv6j2OC7P2IvqQf%2BcZHfQOiQfyUmE68jtiQRx1o52lrYgc3qEaqQ66ey45uHo1AXfu3LFazSA%2BvAPZTlMH6VQG1JnummuZCjE7YK%2FvC7hytT4UxZ0mwoEPS6WnbyPnX4%3Dta260ffa260W1e%5C%2Fnode_modules%5C%2F%2C%20%5C%2F%5C.git%5C%2F%2C%20%5C%2Fobsidian-livesync%5C%2FtfffffffV0tfv2%7B%7DfffA2m8fffA25ka10ttffV0fffffV0A1ata10V60.25.0fVrwss%3A%2F%2Fexp-relay.vrtmrz.net%2FV0V0a10ffV0V0V0Vkself-hosted-livesyncV0V0V0fV0V0V0V0a15V0V0V0ffV0Vdv3-rabin-karpV2v2f

これで設定が完了した。あとは、冒頭の画像のように端末間でのほぼリアルタイム同期が可能となる。

alt text

(再掲) 左がMacOS、右がAndroid(scrcpyで映している)

完全なリアルタイムではないが、Obsidianは共同作業などは前提としていないメモツールなのでこれくらいの遅延は十分許容範囲である。むしろ、複数の端末で同時に編集することはないのでもっと遅くてもいいくらいだ。

感想

Obsidian Self-hosted LiveSyncの完成度の高さと、Tailscaleの便利さにただただ乗っかっただけではあったが、外出先でもVault同期できる環境を構築できた。

ラズパイの電気代を考えると、ランニングコストは月100円前後だろうか。もともとラズパイは起動していたので、増分はもっと少ない。

ただ、確かに金銭面ではObsidian Syncに勝っているが、今後も安定して同期し続けられるという保証はない。 ラズパイに挿しているSDカードの書き込みができなくなるかもしれないし、Community Pluginの開発が止まりObsidianのアップデートに対応できないかもしれないし、原因がすぐに分かるとも限らない。

その都度トラブルシューティングをするなど、突発的にメンテナンスの必要性が生じるかもしれないと考えると、$4/月をObsidianに払うのもいい選択ではある。

Self-hostの最大のメリットは、個人的なメモ書きという手元から離したくないデータを手元で完全に管理できるということではあるが、そのデータを生み出せているのはObsidianというクライアントがあってこそである。Obsidianが継続的に開発して安定的で持続的な運営に寄与することも、大事かもしれない。


Footnotes

  1. 実はMinIOなどのObject Storageの使用もサポートされている


Share this post on:

Next Post
LINE CTF 2024 [Web] jalyboy-baby, jalyboy-jalygirl - Author’s writeup