Clash マルチデバイス設定同期:サブスクリプション・セルフホスト・手動エクスポートの3つの方法
スマホ・PC・タブレット間で設定を揃える方法を比較。サブスクリプションリンクの自動同期、セルフホスト、手動エクスポートの用途・運用コスト・競合の扱いを解説。
まず、同期すべきものは何かを切り分ける
複数のデバイスで「設定が食い違う」とき、原因の多くはクライアント側ではなく、性質の異なるデータをまとめて管理していることにあります。保存場所・更新方法・自動同期の可否はそれぞれ違うので、まず切り分けてから方法を考えます。
| データ | 保存場所 | 自動同期の可否 |
|---|---|---|
| サブスクリプションリンク | 各クライアントの設定保存領域 | 不可。デバイスごとに1回ずつ入力 |
設定本体 config.yaml | クライアントの設定ディレクトリ、またはホスト URL | 可。サブスクリプション取得時に全体が置き換わる |
| ノードとルールセットの providers | ./providers、./ruleset のキャッシュ | 可。interval に従って定期取得 |
| 現在選択中のノード、動作モード | クライアントの実行状態 | 不可。デバイスごとに独立 |
本当に統一すべきなのは設定本体と providers キャッシュです。前者はポート・DNS・TUN・ルールを決め、後者はノード一覧を決めます。どのノードを選んでいるか、mode が rule なのか global なのかは、もともとデバイスごとに設定すべきもので、揃える必要はありません。
よくある誤解:サブスクリプションが同じでも設定は同じにならない
サブスクリプションが決めるのはノードの取得元だけです。mixed-port、dns、tun、rules といったフィールドは各クライアントがローカルで保持しており、サブスクリプションを変えてもポートやローカルルールは同期されません。つまり「3台に同じリンクを入れた」ことと「3台が同じ動作をする」ことは別問題で、後者は以下の方法で担保します。
方法1:サブスクリプションリンクによる自動同期
3台のデバイスに同じサブスクリプション URL を登録し、クライアントが一定間隔で自動取得します。デスクトップ・Android・iOS のいずれも対応しており、もっとも適用範囲が広く、運用コストも最も低い方法です。
「サブスクリプション」→「新規」で URL を貼り付けて保存します。この時点ではプロキシを有効にしないでください。
サブスクリプションのカードを右クリック →「編集」で、自動更新の間隔を既定の 1440 分から 360〜720 分に変更します。
サブスクリプションのカードを右クリック →「更新」で、設定名だけではなくノード一覧が正しく取得できることを確認します。
「設定」→「システムプロキシ」を必要に応じて有効化。TUN モードは「設定」→「TUN モード」で別途オンにします。モバイルではクライアントの VPN サービスが引き継ぐため、追加設定は不要です。
Android は「設定」一覧で設定を長押しすると更新メニューが表示され、iOS は設定の詳細ページを下に引っ張って更新します。
rules、mixed-port、dns のセクションが含まれている場合、更新後はこれらのフィールドがサブスクリプション側の値で上書きされます。自前のルールをサブスクリプションの設定に直接書いてしまうのが、「更新のたびに消える」最もよくある原因です。
ポートが書き換わったときの症状
サブスクリプションによって mixed-port が 7890 から 7891 に変わると、システムプロキシやブラウザ拡張に固定で書かれた 7890 は古いポートを指したままになります。症状は、クライアントは接続済みと表示されるのに Web ページが一切開かないというものです。確認するには external-controller のパネル(既定では 127.0.0.1:9090 をリッスン)を開き、実際に有効なポートを見ます。
# 現在有効なポート・モード・DNS 設定を確認する
curl -s http://127.0.0.1:9090/configs
コマンドラインが使いにくい場合は、デスクトップクライアントの「設定」ページに表示されるポートと、ブラウザ拡張の値を照合するだけで十分です。
適用範囲
- 向いている:デバイス1〜3台、ルールはサブスクリプションに完全追従、追加のファイル管理をしたくない場合。
- 向かない:自前のルールがある、デバイスごとにポートを分けたい、サブスクリプションの構成を頻繁に調整する場合。
方法2:セルフホストで1つの YAML を全デバイスで管理
設定本体を直接ダウンロードできる場所(プライベートなオブジェクトストレージ、自前の nginx、プライベートリポジトリの raw リンクなど)に置き、各デバイスはその URL をサブスクリプションとして読み込みます。以降はルールを変えるときはこの1ファイルだけを編集すれば、各端末が次回取得した時点で反映されます。
ノードの取得元とルールを分離する
ノードを proxies に直接書かず、proxy-providers でカーネル自身に取得させます。ポート・DNS・ルールなど自分で管理する部分は、すべて base config に書きます。
mixed-port: 7890
allow-lan: false
mode: rule
log-level: warning
external-controller: 127.0.0.1:9090
unified-delay: true
tcp-concurrent: true
proxy-providers:
airport-a:
type: http
url: "https://sub.example.com/api/v1/client/subscribe?token=9f2c1a7b4e"
interval: 3600
path: ./providers/airport-a.yaml
health-check:
enable: true
url: https://www.gstatic.com/generate_204
interval: 300
timeout: 3000
rule-providers:
reject:
type: http
behavior: domain
format: mrs
url: "https://example.com/rules/reject.mrs"
path: ./ruleset/reject.mrs
interval: 86400
dns:
enable: true
enhanced-mode: fake-ip
fake-ip-range: 198.18.0.1/16
nameserver:
- https://223.5.5.5/dns-query
fallback:
- https://1.1.1.1/dns-query
2つの interval の単位はいずれも秒です。3600 なら1時間ごとにノードを取得、86400 なら1日ごとにルールセットを取得します。ノードの変動が頻繁なら前者を 1800 に短縮し、ルールセットはそれほど頻繁でなくて構いません。
format: mrs は mihomo 1.18.0 以降が必要で、古いバージョンでは format: yaml と behavior: domain の組み合わせに変更します。また、ホスト URL は直接ダウンロードできる必要があります。プロキシ経由でしかアクセスできない場所に置くと、初回起動時に設定を取得できず、ノード一覧が空になります。
公開前にローカルで構文チェック
# 設定チェックのみ。プロキシは起動しない
mihomo -t -d /etc/mihomo -f config.yaml
チェックを通ってからホスト URL に反映します。各デバイスがホスト URL を読み込んだ後は、ノードは providers が定期取得し、ルールの変更も各端末が設定を再取得するだけで済み、1台ずつ書き換える必要はありません。
フィールドとカーネルバージョンの対応
| フィールド | 対応バージョン | 役割 |
|---|---|---|
format: mrs | mihomo 1.18.0 以降 | ルールセットのバイナリ形式。サイズが小さく、読み込みが高速 |
tcp-concurrent | mihomo 1.16 以降 | 接続の並列確立により、ハンドシェイクの待ち時間を削減 |
unified-delay | mihomo 1.16 以降 | 各プロトコルの遅延測定の基準を統一 |
geodata-mode | mihomo 1.16 以降 | 内蔵 GEO データの利用方法を選択 |
方法3:手動でのエクスポートとインポート
オフラインのデバイス、ルーター、一時的なデバッグにしか使う価値はありません。やり方は設定本体をエクスポートし、providers/、ruleset/ のキャッシュディレクトリも一緒にコピーします。キャッシュディレクトリを欠かすと無駄足になります。
デスクトップクライアントは「設定」で「設定ディレクトリを開く」をクリックします。mihomo のコマンドライン版は通常 /etc/mihomo/config.yaml または ~/.config/mihomo/config.yaml にあります。
config.yaml だけをコピーすると、初回起動時に providers のキャッシュが欠けているためノード一覧が空になります。
たとえば config-20260830.yaml のようにします。同名の設定がクライアント内に複数たまり、互いに上書きし合うのを避けられます。
iOS では先に「ファイル」アプリやクラウドストレージで YAML を端末に保存し、クライアントで「設定をインポート」を選びます。
「プロキシ」ページのノード数と「ルール」ページの件数が、元のデバイスと一致していればインポート成功です。
次のようなケースでは、基本的に手動の方法しか選べません。
- 対象デバイスからホスト URL にアクセスできない場合。たとえば社内ネットワークやオフライン環境。
- 1つのルールや DNS 設定のセットを一時的に検証したいだけで、ホスト側のファイルを触りたくない場合。
- ルーターなどの組み込み環境で、USB メモリや SCP でしかファイルを置けない場合。
競合の処理:変更をレイヤーに分ける
3つの方法を併用すると、競合はほぼ同じ原因から生じます。それは、同じフィールドが2か所で変更されていることです。解決策は変更をレイヤーに分けることです。サブスクリプションやホスト側のファイルには共通部分だけを置き、デバイスごとの差異はマージ層に置きます。
マージ層には差分だけを書く
# Merge 設定:config.yaml 全体を複製せず、変更したい部分だけを書く
prepend-rules:
- DOMAIN-SUFFIX,intranet.example.com,DIRECT
prepend-proxy-groups:
- name: 手動選択
type: select
proxies: [自動選択, DIRECT]
ルールは prepend-rules で先頭に挿入し、サブスクリプション内蔵のルールより優先してマッチさせます。プロキシグループは prepend-proxy-groups で一覧の先頭に置くと、画面上で直接選べて便利です。サブスクリプションを更新してもマージ層の内容は上書きされません。ここが「サブスクリプションの設定を直接編集する」よりも信頼できる点です。
整合性チェックリスト
| 確認項目 | 場所 | 期待する結果 |
|---|---|---|
| 有効なポート | 「設定」→「ポート」、または GET /configs | 各デバイスとも 7890 |
| ノード数 | 「プロキシ」ページ | 同じ provider から取得したノード数が一致 |
| ルール件数 | 「ルール」ページ | ホスト側ファイルの rules の件数と一致 |
| provider の更新時刻 | GET /providers/proxies | interval の範囲内に収まっている |
| 動作モード | トレイメニューまたはホーム画面 | 通常は rule のまま、切り分け時のみ global に切り替え |
# provider の最終取得時刻とノード数を確認する
curl -s http://127.0.0.1:9090/providers/proxies
経験則が1つあります。同じフィールドを定義してよい場所は1か所だけ、ということです。ポート・DNS・TUN は base config に、ノードの取得元は proxy-providers に、デバイスごとの差異はマージ層に書きます。選択中のノードと動作モードは各デバイスに任せます。これを守れば、3台のデバイス間の違いは「今どのノードを選んでいるか」だけになります。
LAN 内で注意すべき2点
external-controllerは既定で127.0.0.1のみをリッスンします。他のデバイスからパネルにアクセスするには、明示的に0.0.0.0:9090に変更し、secretを設定する必要があります。- 複数のデバイスで同時に
allow-lanを有効にしても互いに競合しませんが、他のデバイスは正しいデバイスの IP を指定する必要があります。ポートは 7890 のままで構いません。
3つの方法の選び方
| 方法 | 適した場面 | 運用コスト | 競合の処理 |
|---|---|---|---|
| サブスクリプションリンクの自動同期 | 1〜3台のデバイス、ルールはサブスクリプションに追従 | 低 | それぞれが上書き、ローカルの変更は失われる |
| セルフホスト | 3台以上、自前のルールがある | 中 | マージ層でレイヤー化、競合を予測できる |
| 手動でのエクスポートとインポート | オフラインのデバイス、ルーター、一時的なデバッグ | 高 | 全量上書き、手作業での照合が必要 |
最もよくある組み合わせは、メインのデバイスはホスト URL とマージ層、スマホと予備機はサブスクリプションリンクを直接登録、ルーターのようにネット経由の更新が難しいデバイスは手動でファイルを置く、というものです。3つを併用しても、同じフィールドの定義場所が1か所だけである限り、互いに衝突しません。
よくある質問
スマホと PC に同じサブスクリプションを入れたのに、ノード数が違う
&flag=clash のようなパラメータが欠けると結果が変わります。サブスクリプション更新後にローカルルールが消えた。どう残すか
prepend-rules に入れます。マージチェーンに対応していないクライアントは、自前のホスト URL に切り替え、ルールを base config の rules セクションに書きます。同じ設定が macOS では正常なのに、Android では起動時にエラーになる
tun、redir-port、tproxy-port はデスクトップと Linux 側の書き方で、Android ではクライアント自身の VPN サービスが引き継ぎます。また external-controller を 0.0.0.0:9090 と書きながら secret を設定していないと、一部のクライアントは起動を拒否します。これらのフィールドを base config から外し、各端末のマージ層に移せば解決します。複数のデバイスで同時に TUN モードを有効にすると競合する?
allow-lan を有効にしている場合は、他のデバイスが正しいデバイス IP を指すように注意してください。パネルのポートは既定でローカルのみをリッスンするため、デバイスをまたいでアクセスするには明示的に開放し、secret を設定します。