1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Docker ComposeとCloudflare Tunnelで安全なファイル同期を実現する

1
Last updated at Posted at 2026-08-12

Docker ComposeとCloudflare Tunnelで安全なファイル同期を実現する

対象読者

クラウドを使わずに自宅サーバーで大容量のデータを安全に同期したい方や、DockerとCloudflare Tunnelを使った環境構築でつまずいている方向けの記事です。
他に、デスクトップパソコンとノートパソコンのデータを同期したい人
複数端末でのデータ同期をしたい人向けです
イメージ:PC1<=>Server<=>PC2(Serverにつなげれば複数端末で可能)

はじめに

どうも、CyberToroCTOの丸山です。

今回は、自宅のLinuxサーバー上に「Syncthing」環境をDocker Composeで構築し、Cloudflare Tunnel経由で管理用のWeb GUIを外部から安全に開けるようにした手順をご紹介します。

複数台のPC(デスクトップとノートPCなど)で開発データや個人的なファイルを同期したい場面は多いと思います。Google DriveやDropboxなどのクラウドストレージを使えば簡単ですが、以下のような要件がある場合はSyncthingが非常に強力な選択肢になります。

  • データを外部のクラウドに置きたくない(プライバシー重視)
  • 容量を気にせずテラバイト単位で同期したい(自宅サーバーのHDD依存)
  • 特定のフォルダだけをP2Pで双方向同期したい

本記事では、ただ構築するだけでなく、実際に運用して「ハマったポイント(権限周りやネットワーク経路)」についてもしっかり解説していきます。

使用技術と動作環境

今回の構築で使用した主な環境やツールは以下の通りです。GCPやOpenAIなどのAPIは使いませんが、Cloudflareの無料枠を活用します。

  • OS: Linux(Ubuntu 22.04 LTS 等を想定)
  • Docker: Docker / Docker Compose v2
  • イメージ: lscr.io/linuxserver/syncthing (LinuxServer.ioの公式イメージ)
  • Cloudflare: Cloudflare Tunnel(cloudflared
  • クライアント側: Windows 11 PC (Windows版 Syncthing syncthing.exe を想定)

アーキテクチャ図

まずは全体像を把握するための構成図です。
最大のポイントは「GUIの公開経路」と「ファイル同期の経路」を完全に分離していることです。

Cloudflare TunnelはHTTP(S)の通信をトンネリングする用途には最適ですが、Syncthingの同期プロトコル(TCP/UDP 22000番)のような独自トラフィックは(有償のWARP等を使わない限り)通常のTunnelでは通せません。
そのため、外部からのファイル同期自体はSyncthing標準の「Global Discovery + Relay」機能に任せ、設定をいじるためのWeb GUIだけをCloudflare経由で安全に公開するという設計にしています。


1. ホスト側の事前準備(権限が最重要)

Dockerでファイルサーバー系のコンテナを立ち上げる際、一番つまづくのがパーミッション(権限)エラーです。
今回使用する linuxserver のイメージは、環境変数 PUIDPGID を指定することで、コンテナ内のプロセスを指定したホスト側のUID/GIDで動作させることができます。

まずは自分のユーザーのUIDとGIDを確認します。

# 現在のユーザーのUIDとGIDを確認
id

# 実行結果例: uid=1001(maruyama) gid=1001(maruyama) groups=1001(maruyama),27(sudo),998(docker)

このUIDとGIDに合わせて、ホスト側にデータを永続化するためのディレクトリを作成し、所有権を変更します。ここがズレていると「Permission denied」で同期フォルダが作成できなくなります。

# ディレクトリの作成(設定用とデータ用の2つ)
sudo mkdir -p /srv/syncthing/{config,data}

# 所有権の変更(UIDとGIDが1001の場合)
sudo chown -R 1001:1001 /srv/syncthing

# Dockerが起動していない場合は起動・自動起動化しておく
sudo systemctl enable --now docker

2. docker-compose.yml の作成と解説

ディレクトリの準備ができたら、Docker Composeファイルを作成します。

初期段階では network_mode: bridge でポート(ports: - "8384:8384" など)を公開する設定でも動くには動きます。しかし、同一LAN内のPCからSyncthingを検知しようとした際、Docker内部のIP(172.17.x.x)が広告されてしまい、接続がタイムアウトする現象が多発しました。
Syncthingのローカル発見(Local Discovery)のブロードキャストを正常に機能させるため、最終的には network_mode: host を採用しました。

任意の作業ディレクトリ(例: ~/docker/syncthing)に移動し、以下のファイルを作成します。

# docker-compose.yml
services:
  syncthing:
    image: lscr.io/linuxserver/syncthing:latest
    container_name: syncthing
    hostname: syncthing
    network_mode: host # LAN内でのDiscoveryを正常に動かすため
    environment:
      - PUID=1001 # 先ほど調べたUID
      - PGID=1001 # 先ほど調べたGID
      - TZ=Asia/Tokyo
    volumes:
      - /srv/syncthing/config:/config # 設定・鍵・デバイス情報
      - /srv/syncthing/data:/data     # 同期データの保存先ルート
    restart: unless-stopped
    
  cloudflared:
    image: cloudflare/cloudflared:latest
    container_name: cloudflared-syncthing
    network_mode: host
    restart: unless-stopped
    # トンネルを起動するコマンド
    command: tunnel --no-autoupdate --config /etc/cloudflared/config.yml run
    volumes:
      - ./cloudflared-config.yml:/etc/cloudflared/config.yml:ro
      - ./tunnel-credentials.json:/etc/cloudflared/credentials.json:ro
    depends_on:
      - syncthing

必須ポートとファイアウォール(ufw)の設定

network_mode: host を使用しているため、サーバーのOS側のファイアウォール設定が直接影響します。
Syncthingが使用する主なポートは以下の通りです。

ポート番号 プロトコル 用途
8384 TCP Web GUIアクセス用(今回はCloudflare Tunnel経由でアクセス)
22000 TCP / UDP 実際のファイル同期用トラフィック
21027 UDP 同一LAN上のローカルデバイス発見用(IPv4)

Ubuntu標準のファイアウォール(ufw)を有効にしている場合は、自宅LANのCIDR(例: 192.168.2.0/24)に限定してアクセスを許可しておきます。

# 環境に合わせてLANのセグメントを指定
LAN=192.168.2.0/24

# ルールの追加
sudo ufw allow from "$LAN" to any port 8384 proto tcp comment 'Syncthing Web GUI'
sudo ufw allow from "$LAN" to any port 22000 proto tcp comment 'Syncthing sync TCP'
sudo ufw allow from "$LAN" to any port 22000 proto udp comment 'Syncthing sync UDP'
sudo ufw allow from "$LAN" to any port 21027 proto udp comment 'Syncthing discovery'

# 設定の確認
sudo ufw status numbered

3. Cloudflare Tunnel で GUI を外部公開

Web GUIをインターネットに直接晒すのはセキュリティ上危険です。そこでCloudflare Tunnelを利用し、ポート開放なしで安全にアクセスできるようにします。

まだ cloudflared をホストOSにインストールしていない場合は、公式サイトの手順に従ってバイナリを落とし、ログインを済ませておいてください。

# Cloudflareへのログイン(ブラウザが開くので承認する)
cloudflared tunnel login

# トンネルの新規作成
cloudflared tunnel create syncthing

# DNSレコードのルーティング(例: syncthing.example.com に割り当てる)
cloudflared tunnel route dns syncthing syncthing.example.com

トンネルを作成すると、~/.cloudflared/ ディレクトリに <UUID>.json というクレデンシャルファイルが生成されます。これを docker-compose.yml と同じディレクトリに tunnel-credentials.json としてコピーします。

次に、同じディレクトリに cloudflared-config.yml を作成し、以下のように記述します。

# cloudflared-config.yml
tunnel: <取得したTUNNEL-UUID>
credentials-file: /etc/cloudflared/credentials.json

ingress:
  # ドメインへのアクセスをコンテナの8384ポート(GUI)へ流す
  - hostname: syncthing.example.com
    service: http://127.0.0.1:8384
    originRequest:
      noTLSVerify: true
  # 一致しないアクセスは404で弾く
  - service: http_status:404

ここまで完了したら、コンテナを起動します。

docker compose up -d

ブラウザで https://syncthing.example.com にアクセスし、Syncthingの青いダッシュボード画面が表示されれば成功です。

⚠️ セキュリティに関する注意

公開できたからといって油断してはいけません。以下のセキュリティ対策は必須と考えてください。

  1. GUIのパスワード設定: SyncthingのGUI右上の設定 > GUI から、ユーザー名と強力なパスワードを設定してください。
  2. Cloudflare Accessの設定: Cloudflare Zero Trustのダッシュボードから、このサブドメインに対してメール認証やGitHub認証などのポリシーを追加することをおすすめします。

4. Windows PC との同期手順とハマりポイント

サーバー側の準備ができたので、クライアント(Windows)側を設定します。

公式のWindows Installer版を使うと環境によっては「WSH script registration is not valid」等のエラーでインストールに失敗することがあります。その場合は、GitHubのReleasesからZIP版(syncthing-windows-amd64-vX.Y.Z.zip)をダウンロードし、任意のフォルダに展開して syncthing.exe を直接実行するのが一番確実です。

同期の基本的な流れ

  1. 双方のGUIで「IDを表示」から「デバイスID(長い文字列)」をコピーし、お互いに「リモートデバイスの追加」を行う。
  2. デバイスが相互承認されたら、どちらかのPCで「フォルダを追加」し、共有タブで相手のデバイスにチェックを入れる。
  3. 相手側のGUIに「フォルダの共有リクエスト」が届くので、承認してローカルの保存先パスを指定する。

実運用でハマったポイントまとめ

① Folder Path(保存先)の指定誤り

サーバー側のGUIで同期フォルダを追加する際、パスに /work や相対パス(desktop など)を指定すると、コンテナのルート領域に作ろうとしてしまい「Permission denied / folder path missing」エラーになります。
正しくは、マウントした /data 配下のパス(例: /data/Desktop)を指定してください。

# もしサーバー側で事前にディレクトリを作っておくならこうする
mkdir -p /srv/syncthing/data/Desktop
chown -R 1001:1001 /srv/syncthing/data/Desktop

# Syncthing GUI側のFolder Pathには以下を入力する
/data/Desktop

② ずっと「切断中(未使用)」から進まない

デバイスの追加が完了しても、「切断中」という表示が出る場合があります。これはデバイスが物理的に繋がっていないケースのほか、**「繋がってはいるが、お互いに1つもフォルダを共有していない(未使用)」**という場合にも表示されます。まずは落ち着いてフォルダのShare設定を行ってみてください。

また、LAN内でどうしても互いを見つけられない場合は、リモートデバイスの設定から「アドレス(Addresses)」を dynamic から tcp://192.168.2.148:22000, dynamic のようにサーバーのLAN IPを直接指定すると一発で繋がります。

③ "folder marker missing" の警告で同期が止まる

同期フォルダの直下には、Syncthingが管理用に作る .stfolder という空の隠しディレクトリ(マーカー)が必須です。
「パスを変更した直後」や「誤ってディレクトリの中身を全削除した」場合、このマーカーが消えるとSyncthingは「誤ってデータが消去されたと判断して、他のPCのデータまで巻き添えで消さないように」安全装置として同期を意図的に停止させます。
パスが間違っていないと確信できる場合のみ、対象のディレクトリで mkdir .stfolder を実行してマーカーを手動作成し、GUIで再スキャンをかけてください。

④ 無視パターン(.stignore)の挙動

「このフォルダの中の node_modules.git は同期したくない」という場合はGUIの「無視するパターン」にルールを書きます。
ルート直下の特定のフォルダだけを除外したい場合は、以下のように記述するのが確実です。

/Virtual Machines/
/My Games/
/.git/

注意点として、無視設定は「これから同期するもの」にしか効きません。 すでに同期されてしまったファイルを無視パターンに追加しても自動では消えないため、不要であれば手動で削除する必要があります。


最後に

自宅サーバーにSyncthingを載せること自体はDocker Composeを使えば一瞬ですが、実運用に乗せるまでには「権限(PUID/PGID)」「Folder Pathの指定先」「Dockerネットワークのホストモード」「GUIと同期の経路分離」など、いくつかのつまずきどころがありました。

特にCloudflare TunnelはGUI公開に非常に相性が良く、自宅ルーターのポート開放(穴あけ)なしで出先から安全に管理画面へ入れるのは大きなメリットです。一方で、同期プロトコルそのものはSyncthingネイティブの接続(RelayやLAN直結)に任せるという切り分け設計が重要だと感じました。

自宅サーバーでのファイル同期環境構築の参考になれば幸いです。

参考文献

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?