プログラミング

Obsidian SyncをSyncthingで無料代替する|自宅サーバーで全端末同期

有料のObsidian Syncを、無料のSyncthingで置き換えた記録です。自宅のUbuntuサーバーにDockerでSyncthingを立て、サーバー・Windows・Androidスマホの3台でObsidianのvaultを双方向同期しています。実際に使っているdocker composeの内容、4つのポートの役割とUFWの開け方、.stignoreとバージョニングの設定、Claude Codeへの指示書までまとめました。

目次

はじめに

Obsidianを複数の端末で使っていて、「同期のためだけに月額を払うのはちょっとなあ」と思ったことはありませんか。

Obsidianには公式の同期サービス「Obsidian Sync」がありますが、これは有料です。
私もパソコンとスマホの両方でメモを取るので同期は必須なのですが、自宅サーバーを立てたタイミングで「これ、自前でできないかな」と考えました。

結論から言うと、Syncthing(シンクシング)という無料のツールで、Obsidian Syncはきれいに置き換えられました。
今では、サーバー・Windows・Androidスマホの間で、同じObsidianのメモが自動で同期されています。

この記事では、私が実際に動かしている設定値(イメージ名・ポート番号・環境変数・マウント先)と、コピーして使える構成ファイルまで具体的に書きます。
記事の後半には、Claude Codeへの指示書も載せておきます。
土台にしているのは、古いWindows機にUbuntuを入れて作った自宅サーバーで、外出先からのアクセスにはTailscaleを併用しています。
Obsidianを使っていない方でも、「複数の端末でフォルダを同期したい」という用途にそのまま応用できる内容かと思います。

Syncthingとは何か

Syncthingは、複数の端末の間でフォルダを同期し続けてくれる、無料のオープンソースのツールです。
特徴を、ふだんクラウドサービスを使っている感覚との違いも含めて挙げてみます。

  • どこかの会社のサーバーに預けない:これがいちばん大きな違いです。一般的なクラウド同期は、いったん業者のサーバーにファイルを預けて、そこを経由して各端末に配ります。Syncthingは、自分の端末同士が直接ファイルをやり取りします。この「端末同士が直接つながる」方式を、専門的にはP2P(ピアツーピア)と呼びます。
  • 無料:オープンソースなので料金がかかりません。
  • 常に同期し続ける:ファイルを変更したら裏で自動的に他の端末へ反映されます。
  • 暗号化されている:端末同士のやり取りは暗号化されるので、途中の通信をのぞき見される心配が少ない作りです。

もう少し仕組みを補足します。
Syncthingでは、それぞれの端末にデバイスIDという長い文字列(端末を一意に表す識別子)が割り当てられます。
中央のサーバーやアカウントにログインするのではなく、つなぎたい端末どうしが互いのデバイスIDを登録して「この相手を信頼します」と承認し合うことで、はじめて接続が成立します。
そして同期はフォルダ単位で、「このフォルダを、このデバイスIDの相手と共有する」と指定して広げていきます。
アカウントもパスワードのやり取りもなく、デバイスIDの相互承認だけでつながる相手を限定する、というのがSyncthingの根っこの考え方です。

Obsidianの正体は「Markdownという形式のテキストファイルが入った、ただのフォルダ」です。
ですから、そのフォルダをSyncthingで同期してあげれば、結果としてObsidian Syncと同じこと(複数端末で同じメモを共有する)が実現できる、というわけです。
本記事は、このObsidianのフォルダ(vault)を、サーバー・パソコン・スマホで双方向に同期することを主眼にしています。

全体の構成を決める

私の構成はこんな形です。

サーバー・Windowsパソコン・Androidスマホそれぞれの役割

ポイントは、24時間動いているサーバーを同期の「拠点」にすることです。
Syncthingは端末同士が直接つながる仕組みなので、理屈の上ではパソコンとスマホだけでも同期できます。
ただ、パソコンもスマホも、いつも電源が入っているわけではありません。
両方ともオフのあいだに片方だけ変更があると、もう片方に追いつくきっかけがありません。
そこで、いつでも起動しているサーバーを真ん中に置くと、どの端末を立ち上げても、まずサーバーと同期して最新の状態に追いつけます。

ステップ1:サーバーにSyncthingを入れる

CasaOSのアプリ管理画面からでも入れられますが、ここでは何を設定しているかが分かる構成ファイル(docker compose)で示します。
中身が分かれば、CasaOSの画面で同じ値を入れるのも、Claude Codeに作ってもらうのも簡単になります。
Syncthingも、これまでと同じようにDocker(アプリを箱に詰めて動かす仕組み)の上で動かすので、サーバー本体の環境を汚さずに導入できます。
私が実際に動かしているのは、おおむね次の内容です。

services:
  syncthing:
    image: syncthing/syncthing:2.0
    ports:
      - "8384:8384"               # 管理画面(Web UI)
      - "22000:22000/tcp"         # 端末間の同期通信(TCP)
      - "22000:22000/udp"         # 端末間の同期通信(UDP)
      - "21027:21027/udp"         # 同じLAN内の端末の自動検出
    environment:
      - PUID=1000                 # 作られるファイルの持ち主(自分のユーザー番号)
      - PGID=1000                 # 同じくグループ番号
      - STGUIADDRESS=0.0.0.0:8384 # 管理画面を箱の外から開けるようにする
      - STHOMEDIR=/var/syncthing/config  # 設定の保存先(下のマウントと対応)
    volumes:
      - /DATA/AppData/syncthing/data:/var/syncthing          # 設定と同期データ本体
      - /DATA/AppData/syncthing/media:/media/data/syncthing  # 追加のデータ置き場
    restart: unless-stopped

設定の意味を、効いてくる順に説明します。

  • image: syncthing/syncthing:2.0:公式イメージのv2.0系を使っています。latest ではなくバージョンを指定しておくと、ある日勝手に大きく挙動が変わって戸惑う、ということが起きにくくなります。
  • ports の4つ:それぞれ用途が違うので、次のステップ2で表にして詳しく説明します。ここでは「管理画面・同期通信・自動検出で、開ける口が分かれている」とだけ押さえてください。
  • PUID=1000 / PGID=1000:コンテナの中で作られるファイルを、サーバー側の自分のユーザー(一般ユーザーの番号、私の環境では1000)の持ち物にする指定です。自分の番号は、サーバーで id コマンドを打つと確認できます。これを合わせておかないと、できあがったファイルが「管理者(root)の持ち物」になってしまい、後からObsidianやエディタで普通に編集・削除できずに困ることがあります。同期したファイルを自分でも触る前提なので、ここは必ず合わせます。
  • STGUIADDRESS=0.0.0.0:8384:管理画面をどのアドレスで待ち受けるかの指定です。0.0.0.0 は「箱の外からの接続も受け付ける」という意味で、これがないとDockerの箱の中からしか管理画面を開けません。別の端末のブラウザから開きたいので、こう指定しています(外部に晒すかどうかは、ポートを開けるかどうか=ステップ2のファイアウォールで別途しぼります)。
  • STHOMEDIR=/var/syncthing/config:Syncthingが自分の設定(デバイスIDや、どのフォルダを誰と共有しているか)を保存する場所です。下のマウントでこの場所をホスト側の /DATA に逃がしているので、コンテナを作り直してもデバイスIDや共有設定が消えません。
  • volumes(マウント):コンテナの中の保存先を、ホスト(サーバー本体)の /DATA の下のフォルダに対応づけています。同期されたファイルの実体がサーバーの /DATA の下に残るので、バックアップの対象にそのまま含められますし、上の PUID / PGID と合わせて自分でも直接触れます。

導入が終わると、ブラウザでサーバーのアドレスにポート番号「8384」を付けて http://(サーバーのIP):8384 にアクセスすると、Syncthingの管理画面(Web UI)が開きます。

ステップ2:通信の出入り口とセキュリティを整える

Syncthingは端末同士が直接やり取りするので、その通信が通る出入り口を用意します。
Syncthingが使う主なポートは、次の3つです。

Syncthingが使う3つのポートと用途・通信の種類

21027は「同じLAN内の自動検出」用で、その性質上、家のネットワークの外には出ていきません。
なので外向けに考えるのは8384と22000の2つです。
ここで意識したのは、「設定画面(8384)は外に出さない/同期の通信(22000)だけは外からも届くようにする」という分け方です。
土台を作ったときに入れたファイアウォール(UFW)で、こう設定しています。

sudo ufw allow 22000/tcp                                          # 同期通信はインターネットからも受ける
sudo ufw allow from <自宅LANの範囲> to any port 8384 proto tcp    # 管理画面は自宅LANから
sudo ufw allow from <Tailscaleの範囲> to any port 8384 proto tcp  # 管理画面は自分のTailscale端末から
  • 同期の通信(22000):外出先のスマホとサーバーが、リレーに頼らず直接同期できるよう、ここはインターネット側からも届くように開けます(22000/tcp)。
  • 設定画面(8384):自宅のLANと自分の端末からだけ開ければ十分なので、from で送信元を自宅LANの範囲とTailscaleの範囲に限定します。インターネット側からは開きません。

<自宅LANの範囲> には自宅ネットワークの範囲(ご家庭により異なります。サーバーを立てたときに調べた値)を、<Tailscaleの範囲> にはTailscaleが各端末に割り当てる専用アドレスの範囲(Tailscaleの管理画面やドキュメントで確認できます)を入れます。

「同期の通信を外に開けて大丈夫なの?」と不安に思うかもしれません。
ですが、Syncthingの同期は、前の節で触れたデバイスIDの相互承認を済ませた相手としかつながらず、しかもやり取りは暗号化されています。
22000を開けても、承認していない誰かと勝手にデータをやり取りすることはありません。
一方で、管理画面(8384)は、開けてしまうと共有設定やフォルダ構成を外からのぞける入り口になり得ます。
だから「同期の口(22000)は開ける/管理の口(8384)は身内だけ」と、役割で分けて開け閉めしています。
これは、他の管理用の画面を外に晒さないようにしているのと同じ考え方です。

ステップ3:フォルダと端末を登録する

Syncthingの設定画面で、同期したいフォルダ(=Obsidianのメモが入ったフォルダ)を登録します。
私が同期しているのはObsidianのフォルダ1つだけで、分かりやすいラベル(名前)を付けて管理しています。

次に、各端末にもSyncthingを入れて、お互いを「相手の端末」として登録し合います。
スマホはAndroid版のSyncthingアプリ、WindowsはWindows版のSyncthingを使います。
冒頭で触れたデバイスIDの出番がここです。
各端末の管理画面に表示される自分のデバイスIDを相手に登録し、両側で承認し合うと接続が成立します。
サーバーを拠点にする構成なので、まずパソコンとサーバー、次にスマホとサーバー、というように、それぞれをサーバーと承認させていくと整理しやすいです。

フォルダを共有するときに、もう一つ知っておくとよいのがフォルダの種類です。
それぞれの端末で、そのフォルダを「送受信(書き換えも反映する)」「受信のみ(受け取るだけ)」などに設定できます。
普通にどの端末でも編集したいなら、すべて「送受信」にしておけば大丈夫です。
一度お互いを承認し合えば、あとは勝手に同期が始まります。

ステップ4:各端末のObsidianから同じフォルダを開く

ここまで来れば、あとはObsidian側の設定だけです。
各端末で、Syncthingが同期しているフォルダを、そのままObsidianのメモ帳(vault)として開くだけです。

  • Windows:同期フォルダを「既存のフォルダをvaultとして開く」で指定します。
  • Android:Obsidianアプリでも、同じく同期フォルダを指定します。

これで、パソコンで書いたメモがスマホに、スマホで取ったメモがパソコンに、サーバーを経由して反映されるようになります。
私の環境では、家の中のネットワークなら、編集してから他の端末に反映されるまでほぼ一瞬という感覚です。

ひとつ補足です。
Syncthingには、Obsidianが内部で作る一時ファイルや、同期したくないファイルを除外する仕組み(同期フォルダの直下に置く .stignore という設定ファイル)があります。
私はObsidianのvaultで、だいたい次のような内容を入れています。

.trash
.obsidian/workspace.json
.obsidian/workspace-mobile.json
.DS_Store

.trash はObsidianのゴミ箱、workspace.json 系は「どのタブをどう開いていたか」という端末ごとの画面状態です。
これらは端末ごとに違って当然のものなので、同期から外しておくと、開くたびにレイアウトが書き換わったり、後述の競合ファイル(sync-conflict)が無駄に増えたりするのを防げます。
逆に、メモ本体や .obsidian の中のプラグイン・設定(テーマやホットキー)は同期したいので、除外しすぎないのがコツです。

さらに、誤って消したり上書きしたりしたファイルを一定期間とっておく「ファイルバージョニング」という機能もあります。
フォルダの設定で「Staggered(段階的)」などを選んでおくと、最近のものは細かく、古いものは間引いて、一定期間ぶんの旧版を保持してくれます。
これをオンにしておくと、うっかりミスや、後述の競合からメモを取り戻せて安心です。

なぜ反映がこんなに速いのかも触れておきます。
Syncthingは、フォルダの変更をOSの「ファイル監視」の仕組みで即座に拾い、念のため一定間隔での再スキャンも併用しています。
そして、変わったファイルを丸ごと送り直すのではなく、ファイルを小さなかたまり(ブロック)に分けて、変わったブロックだけを相手に送ります。
だから、長いメモの末尾に一行足しただけなら、送られるのはそのわずかな差分だけで済みます。
テキスト中心のObsidianとは特に相性がよく、古い回線のサーバーでもきびきび同期できます。

Claude Codeへの指示書

ここまでの構築を実際にやってもらうための、Claude Codeへの指示書を載せておきます。
サーバーにClaude Codeを入れてあれば、これをそのまま貼り付けて渡すだけで、サーバー側の準備を一緒に進めてくれます。
本文で出した値(イメージ syncthing/syncthing:2.0・4つのポート・PUID / PGID は1000・8384と22000の開け方の違い)を、そのまま方針として渡しています。
スマホや別の端末側のアプリ導入は、最後に自分で行います。

あなたはこのUbuntuサーバーの構築を手伝うエンジニアです。
私は非エンジニアなので、専門用語は噛み砕いて、操作の前には何をするか一言説明してください。

目的:有料のObsidian Syncの代わりに、Syncthingで自分のObsidianのメモを
複数端末(このサーバー・パソコン・スマホ)で同期できるようにしたい。

次の手順で進めてください。
1. docker compose で Syncthing(syncthing/syncthing:2.0)を起動する設定を作る。
   - ポートは 8384(管理画面)、22000/tcp と 22000/udp(同期)、21027/udp(LAN自動検出)を公開。
   - 環境変数は PUID=1000、PGID=1000、STGUIADDRESS=0.0.0.0:8384、STHOMEDIR=/var/syncthing/config。
   - 設定と同期データの保存先は /DATA の下にマウントし、作られるファイルが
     自分のユーザー(PUID/PGID=1000)の持ち物になるようにすること。
2. ファイアウォール(UFW)を設定する。
   - 同期ポート 22000/tcp はインターネットからも届くように開ける。
   - 管理画面のポート 8384 は自宅LANと自分の端末(Tailscaleの範囲)からだけに制限する。
3. 管理画面の開き方(アドレスとポート8384)を教えてほしい。
4. 同期したいフォルダ(私のObsidianのフォルダ)を登録する手順と、
   一時ファイルを除外する .stignore、ファイルバージョニングの設定も案内してほしい。
各ステップで、何をしたか・次に私が手元の端末で何をすればいいかを説明してください。

「目的」と「使う値」を箇条書きで渡すのがコツです。
イメージ名・ポート・環境変数まで指定しておくと、細かいコマンドはClaude Codeがその値どおりに組み立ててくれます。

外出先からでもつながる仕組み(リレー)

「家の外にあるスマホと、家の中のサーバーが、どうして直接つながれるの?」と疑問に思うかもしれません。
Syncthingには「リレー」という仕組みが用意されていて、お互いが直接つながれないときは、世界中にあるボランティアの中継地点(リレーサーバー)を経由して、暗号化したまま橋渡ししてくれます。
中継地点を通る場合でも中身は暗号化されたままなので、メモの内容が読まれることはありません。
直接つながれるときは直接、無理なときはリレー経由、と自動で切り替わります。

なお、Tailscaleをオンにしている端末同士なら、Syncthingの通信もテールネット経由で安定して直接つながるので、リレーに頼らずに済むことも多いです。
設定画面を外から開きたいときも、Tailscale経由でアクセスすると安全です。

よくあるトラブルと対処

つまずきやすい点をQ&Aでまとめておきます。

Q. 端末同士がなかなか「接続済み」にならない

両方の端末でSyncthingが起動しているかを確認し、お互いのデバイスIDを正しく登録して両側で承認できているかを見直します。
初回は相手を見つけるまで数分かかることもあるので、少し待ってみるのも有効です。

Q. 最初の同期がなかなか終わらない

メモやファイルの量が多いと、初回の同期には時間がかかります。
画面に同期の進み具合(パーセント)が出るので、数字が進んでいれば正常です。
完了するまで、サーバーと端末を起動しておきましょう。

Q. sync-conflict という名前のファイルが増えてしまった

これは、複数の端末で同じファイルをほぼ同時に編集したときにできる「競合ファイル」です。
元のファイルと競合ファイルの中身を見比べて、新しいほうを残し、不要な競合ファイルは削除すれば片付きます。
「1つの端末で書いたら、少し待って同期させてから次の端末で開く」と意識しておけば、まず起きません。

Q. スマホだけ同期が止まっているように見える

Androidの省電力機能でアプリが眠らされている可能性が高いです。
スマホの設定でSyncthingアプリを「バッテリー最適化の対象から外す」と安定します。

まとめ

いかがでしたか。
今回は、有料のObsidian Syncを、無料のSyncthingで置き換える方法を紹介しました。

手順を振り返ると、次の4ステップです。

  1. サーバー(CasaOS)にSyncthingを入れ、保存先を /DATA の下に、持ち主を自分のユーザーにする
  2. 同期ポート(22000)は開け、設定画面(8384)は自宅とTailscaleだけに絞る
  3. 同期したいフォルダと端末をお互いに承認して登録する(フォルダの種類・除外設定・バージョニングも)
  4. 各端末で、その同期フォルダをObsidianのメモ帳として開く

一度設定してしまえば、あとは勝手に同期され続けます。
Obsidian以外でも「複数の端末で同じフォルダを共有したい」という場面はよくあると思うので、ぜひ試してみてください。

同じ自宅サーバーでは、Google Driveの代わりになるNextcloudや、Googleフォトの代わりになるImmichも動かしています。
そちらもそれぞれ別の記事にまとめてあります。

この記事が誰かの役に立てばうれしいです。