SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

RustDeskのリレーサーバーをVPSで自前運用する方法

VPSでRustDeskのhbbsとhbbrを自前運用する手順です。Ed25519鍵、固定したイメージタグ、公開ポートの制限、プラン料金に直結するリレー帯域を確認できます。

自己ホスト型 RustDesk リレーサーバーとは

自己ホスト型 RustDesk リレーサーバーは、1 台の VPS 上で動作する 2 つのデーモンです。hbbs は ID サーバー兼ランデブーサーバーです。すべてのクライアント ID を登録し、2 つのクライアントを相互に紹介します。hbbr はリレーサーバーです。直接通信できなかったセッションに限り、セッションのデータを中継します。多くのガイドは両方をインストールして接続を確立するところで終わります。ここでは、その後に必要な作業を説明します。アクセス制御に使う鍵、ポート、アップグレード、帯域幅を扱います。

両方のデーモンは同じイメージ rustdesk/rustdesk-server に含まれています。以下の構成では、両方が同じディレクトリにある同じ Ed25519 鍵ペアを読み込みます。これは自分で設定する項目です。デフォルトの動作ではありません。hbbs は自動的に鍵ペアを読み込むか生成しますが、hbbr は鍵を指定して起動しない限り鍵を無視します。Ed25519 は公開鍵署名方式です。この鍵ペアによって、サーバーが通信するクライアントが決まります。背後にユーザーデータベースはありません。

hbbs と hbbr: 帯域幅を消費するデーモン

hbbs のトラフィックは少なく、一定です。ID の登録とハートビートに加え、2 台のピアを接続するための短い通信が発生します。終日稼働しますが、コストはほとんどかかりません。

hbbr のトラフィックがセッション本体です。画面フレームは一方向に、キーボードとマウスの入力は反対方向に送信されます。中継されるすべてのバイトは VPS に到着し、そこから再び送信されます。プロバイダーが外向きトラフィックだけを計測する場合、中継セッションによるコストはセッションの通信量とほぼ同じです。総転送量を計測する場合は、ほぼ 2 倍になります。

リレーは通常の経路ではなく、フォールバックです。hbbs はまず、各クライアントの前段にある NAT (network address translation) を通じたホールパンチングを使い、2 台のクライアントを直接接続しようとします。これが成功すれば、セッションは hbbr を経由せず、転送量も消費しません。一方が接続先ごとに新しいポートを割り当てる NAT の背後にある場合や、ホールパンチングで確立した経路をファイアウォールが破棄する場合、セッションは hbbr にフォールバックします。その場合、すべてのフレームが VPS を通過します。

1 つの環境変数で、この選択をなくせます。hbbs の ALWAYS_USE_RELAY=Y は、すべてのセッションを hbbr 経由にします。RustDesk のドキュメントにある Compose の例の 1 つで使用されているため、よくコピーされています。これにより接続は予測しやすくなりますが、外向きトラフィックも実際に発生します。貼り付けたからではなく、自分で決めた場合に設定してください。

セルフホストの RustDesk サーバーに必要なポート

以下のポート番号は、2026 年 10 月 10 日に RustDesk サーバーのドキュメントと rustdesk-server リポジトリを照合して確認したものです。

  • TCP 21115、hbbs: NAT タイプのテスト。
  • UDP 21116、hbbs: ID 登録とハートビート。クライアントはデフォルトでこの経路を使用します。
  • TCP 21116、hbbs: TCP のみを使用するよう設定したクライアントの ID 登録、TCP ホールパンチング、接続サービス。
  • TCP 21117、hbbr: リレー。セッションデータを転送するポートであるため、通信費が発生するポートです。
  • hbbs の TCP 21118 と hbbr の TCP 21119: ブラウザクライアントが使用する WebSocket。使用しない場合は、両方とも閉じたままにします。
  • TCP 21114: RustDesk Server Pro の HTTP API サーバー。オープンソース版はこのポートで待ち受けません。

hbbs と hbbr をイメージタグを固定してインストールする

services:
  hbbs:
    container_name: hbbs
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbs
    volumes:
      - ./data:/root
    network_mode: "host"
    depends_on:
      - hbbr
    restart: unless-stopped

  hbbr:
    container_name: hbbr
    image: rustdesk/rustdesk-server:1.1.16
    command: hbbr -k _
    volumes:
      - ./data:/root
    network_mode: "host"
    restart: unless-stopped
mkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose ps

両方のサービスが running を読み込むようにします。ファイアウォールを変更する前に、リスナーが存在することを確認してください。

sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'

TCP リスナーとして 21115、21116、21117 が表示され、UDP リスナーとして 21116 が表示されます。UDP の行がない場合、hbbs は実行されていません。hbbs は起動時にこのリスナーを開き、クライアントはデフォルトでこのリスナーに対して登録するためです。

このファイルでは、4 つの点を意図的に指定しています。タグは 1.1.16 です。これは 2026 年 10 月時点の現行リリースで、2026 年 7 月 20 日に公開されたものです。latest ではありません。latest は最後に push されたイメージを意味するため、6 か月後の docker compose pull に、テストしていないサーバーが配布される可能性があります。network_mode: "host" はホストのインターフェースに直接バインドします。これは RustDesk のドキュメントが推奨する方法であり、ファイアウォールの動作にも影響します。./data:/root はイメージの作業ディレクトリをホストにマッピングするため、鍵ペアをバックアップ可能な場所に保存できます。hbbr -k _ は upstream の例から変更した唯一の点です。デフォルトの設定では、誰でもリレーを利用できる状態になるためです。Compose が初めての場合は、VPS で Docker Compose を実行するでファイル形式とライフサイクル用コマンドを説明しています。

hbbr を別のサーバーへ移行する場合は、hbbs に移行先を伝える必要があります。-r relay.example.com:21117 を渡すか、RELAY-SERVERS 環境変数を設定してください。1 台のサーバーで運用する場合は不要です。

Ed25519 鍵ペアがアクセス制御を担います

初回起動時に hbbs は作業ディレクトリ内に id_ed25519 と id_ed25519.pub を生成します。上記のマウント設定により、両方のファイルがホスト側に表示されます。

ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pub

id_ed25519.pub には base64 文字列が 1 つ格納されます。この文字列をすべてのクライアントの Key フィールドに入力します。id_ed25519 は秘密鍵であり、サーバーの外部には出しません。公開鍵は、すべてのクライアント設定にコピーするため、秘密情報ではありません。秘密鍵は秘密情報です。秘密鍵を持つ人は、クライアントが信頼するサーバーを構築できます。

クライアントを 20 台設定する前に、今すぐ両方のファイルをバックアップしてください。

sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgz

そのアーカイブをサーバーの外部へコピーしてください。この作業が他のどの手順より重要である理由を説明します。~/rustdesk/data を削除した場合、またはこのファイルをコピーせずに新しい VPS へ再構築した場合、hbbs は次回の起動時に新しい鍵ペアを生成します。すべてのクライアントには古い公開鍵が残っているため、hbbs は接続を拒否し、クライアントはオフラインになります。sudo cat ~/rustdesk/data/id_ed25519.pub を実行し、任意のクライアントの Key フィールドと比較してください。2 つの文字列は一致しなくなり、この不一致が障害の原因です。修復するには、各マシンの設定を手動で編集する必要があります。RustDesk で接続する予定だったマシンも対象です。

この鍵はセッションパスワードではありません。両者を混同すると、どちらか一方を省略してしまいます。この鍵は、サーバーが通信するクライアントを決定します。管理対象マシンの永続パスワードまたはワンタイムコードは、そのマシンでセッションを開けるユーザーを決定します。両方が必要です。一方があるからといって、もう一方の弱さを補えるわけではありません。

認証なしのリレーが問題になる理由

デフォルトでは、hbbr は何も検証しません。RustDesk の設定ドキュメントにも明記されています。空の key を指定すると、一致する key を持たないクライアントでもリレーを使用できます。空のデフォルト値は、初回起動時に新規ユーザーが key の不一致で失敗しないようにするためのものです。その代わり、TCP 21117 上のアドレスを知っている誰でも、あなたの VPS を経由してセッション通信を送信できます。通信量はあなたの転送量枠を消費し、送信元 IP アドレスにはあなたの IP アドレスが使われます。

command: hbbr -k _でこの状態を解消できます。_引数を指定すると、hbbr は作業ディレクトリから key pair を読み込み、存在しない場合は生成します。両方のコンテナが同じ ./dataをマウントするため、hbbs が使用するものと同じ key pair になります。手動でコピーするものがないため、内容がずれることもありません。

共有ボリュームの扱いを誤るケースが多くあります。hbbr 用に別のディレクトリを割り当てると、hbbr は別の key pair を生成します。その結果、hbbs と hbbr の key が一致せず、リレー経由のセッションはすべて失敗します。一方、直接接続のセッションは動作し続けます。症状が分かりにくいのは、hole punching が成功したかどうかによって、RustDesk が接続できるピアと接続できないピアに分かれるためです。1 つの ls -l ~/rustdesk/data/に id_ed25519 pair が 1 つだけ表示されれば、この不一致を除外できます。ただし、リレーが key を検証していることの証明にはなりません。hbbr は空でない key を指定して起動しない限り、これらのファイルを無視するためです。そのため、実行中のコマンドも確認します。

ps -eo args | grep '[h]bbr'

hbbr -k _と表示されるはずです。単独の hbbrと表示される場合は、ディレクトリ内に何があっても、リレーはまだ公開されたままです。

クライアントをサーバーに接続する

各マシンで RustDesk を開き、Settings、Network、ID/Relay Server の順に開きます。

  • ID Server: サーバーのホスト名を指定します。例: rustdesk.example.com。クライアントは、別のポートを記述しない限り 21116 番ポートを使用します。
  • Relay Server: hbbr が hbbs と同じホストで実行されている場合は空欄にします。
  • API Server: 空欄にします。オープンソース版のサーバーには API Server がありません。
  • Key: id_ed25519.pub の base64 文字列を、末尾に空白を付けず、そのまま貼り付けます。

その後、メインウィンドウにクライアントの準備が完了したことが表示されます。表示されず、クライアントがデフォルト設定で動作している場合は、通常、UDP 21116 が hbbs に到達していません。デフォルトのクライアントは、このポートで登録し、heartbeat を送信するためです。ただし、オフライン ID だけでは原因を特定できません。disable-udp オプションが Y に設定されたクライアントは TCP 21116 で登録し、UDP 21116 を使用しません。そのため、そのクライアントでは最初に TCP 21116 を確認します。

リレーを公開サービスにしないようポートを制限する

コンテナは host networking を使用するため、コンテナの前段に Docker の NAT ルールはありません。そのため、ufw のルールは想定どおりに適用されます。

sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numbered

ブラウザクライアントを使用する場合に限り、21118:21119/tcp を追加します。ufw を有効にする間は、SSH のセッションをもう1つ開いたままにしてください。SSH のルールを誤ると、自分のサーバーから締め出される可能性があります。VPS の ufw ファイアウォールの基本では、デフォルトポリシーとルールの適用順を説明しています。

ここで注意が必要です。多くの単一コンテナ RustDesk の例で使用されている ports: ブロックによるポート公開に切り替えると、Docker が独自の DNAT ルールを書き込みます。その場合、パケットは ufw のルールが存在するチェーンを通らずにコンテナへ到達します。したがって、21117 に対する ufw の deny は効果がなく、ufw status がそうでないと示していても、リレーはインターネットに公開された状態になります。Docker の公開ポートが ufw を迂回する仕組みでは、チェーンの適用順を説明しています。Host networking を使用すれば、この問題を完全に回避できます。ポートを公開する場合は、リバースプロキシの背後にある "127.0.0.1:21118:21118" のように、1つのアドレスにバインドしてください。

送信元アドレスによる制限が有効なのは、クライアントのアドレスが安定している場合だけです。

sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udp

ホテルのネットワークに接続するラップトップは安定したアドレスを持たないため、この構成ではファイアウォールよりも hbbr の key のほうが実際の防御に大きく貢献します。

鍵を保持するスタックのアップグレード

鍵はコンテナ内ではなく bind mount に保存されるため、./dataを変更しなければ安全にアップグレードできます。

  1. 最初にデータディレクトリをバックアップします: sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data。
  2. rustdesk-server の releases ページで、新しい tag のリリースノートを確認します。
  3. compose.ymlを編集し、2 つの image:行を新しい tag に変更します。
  4. sudo docker compose pullを実行し、その後 sudo docker compose up -dを実行します。
  5. sudo cat ~/rustdesk/data/id_ed25519.pubを実行し、その文字列がすでにクライアントに保存されているものと一致することを確認します。

重要なのは Step 5 の確認です。鍵が変更されてもサーバー側では通知されず、すべてのクライアントが同時に接続できなくなるためです。ロールバックするには、古い tag に戻して up -dを再度実行します。これは tag を固定していた場合にのみ機能します。latestでは、docker compose pullが名前を新しいイメージに移したため、古いイメージを指す tag が残らないためです。

鍵を失う通常の原因は、bind mount をそのまま保持する docker compose downではありません。新しい VPS へ移行し、compose.ymlだけをコピーすることです。./dataも一緒にコピーしてください。

転送量上限のあるプランで外向き通信量を監視する

この構成で転送量上限を消費する可能性があるのは hbbr だけです。RustDesk の FAQ では、1920x1080 の画面でリレー接続 1 本を使用した場合、通信量は 30 KB/s から 3 MB/s とされています。また、通常のオフィス作業は約 100 KB/s とされています。これらは 1 セッションあたりの公表値であり、実際の環境で測定した値ではありません。1 日 2 時間、月 60 時間として換算すると、次のようになります。

グラフVPS egress from one relayed RustDesk session, 60 hours per month
このグラフのデータ
[
  {
    "label": "Low end, 30 KB/s",
    "gb_per_month": 6.5
  },
  {
    "label": "Office work, 100 KB/s",
    "gb_per_month": 21.6
  },
  {
    "label": "High end, 3 MB/s",
    "gb_per_month": 648
  }
]

オフィス作業の通信量では、1 セッションあたりの月間使用量は約 21.6 GB です。この程度なら、どのプランでも問題になりません。公表範囲の上限では、同じ 60 時間で 648 GB になります。この速度で 2 セッションを同時に使用すると、月内に 1 TB の上限を超えます。下限では 6.5 GB です。ここでの GB は 1000 MB を意味します。転送量上限では通常この単位で計算されます。

docker stats では、この内訳を確認できません。ホストネットワークを使用するコンテナはホストのネットワーク名前空間を共有するため、コンテナのカウンターがホストのカウンターになるからです。使用できるツールはほかに 2 つあります。vnstat ではサーバー全体を測定します。

sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -m

サーバー全体とは、本当にサーバー全体です。この VPS で実データを転送する別のサービスも動いている場合、たとえば毎晩スマートフォンのライブラリを取得する 自ホスト型の写真サーバーなどでは、そのアップロードもリレー通信と同じ月間使用量に加算されます。メディアサーバーも同様です。たとえば、Jellyfin ライブラリを閲覧可能な 90 年代風のビデオストアに変える Halcyonのようなサービスは、視聴者にデータをストリーミング配信します。この外向き通信も、リレーが使用する転送量上限を共有します。

nftables のカウンターを使用すると、リレーの通信量だけを測定できます。

sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeter

このルールは判定を行わないため、許可される通信を変更せずにパケット数とバイト数だけをカウントします。また、独立したテーブルに置かれるため、ufw の動作を妨げません。永続化されないため、再起動後も復元したい場合は同じ行を /etc/nftables.conf に記述します。カウンターが増加するのは、実際にセッションが中継されている間だけです。自分のマシンが接続していないのにカウンターが増え続ける場合は、第三者にリレーを発見されています。これを防ぐために hbbr -k _ が存在します。毎朝 nft list を確認することはないため、バイト数をしきい値と比較し、超過時にプッシュ通知を送る cron ジョブを設定します。この用途には 自分で運用する ntfy サーバー が適しています。

hbbr には下げられるレート制限もあります。SINGLE_BANDWIDTH のデフォルト値はリレー接続 1 本あたり 128 Mb/s、TOTAL_BANDWIDTH のデフォルト値は全接続の合計で 1024 Mb/s です。SINGLE_BANDWIDTH=8 を設定すると、1 セッションあたりの速度を約 1 MB/s に制限できます。これは速度を制限するものであり、月間の合計通信量を制限するものではありません。そのため、1 セッションが回線を占有するのを防ぐ手段として使用し、転送量の予算管理には使用しないでください。

リレーがまったく不要な場合

個人利用では、そもそもこれらが不要な場合があります。2 台のマシンをメッシュ VPN に接続し、トンネルのアドレスへ直接接続します。hbbs も hbbr も、リレー経由の送信も、VPS 上でアップグレードするコンテナも必要ありません。

操作対象のマシンで、RustDesk のセキュリティ設定から直接 IP アクセスを有効にします。ポート欄のデフォルト値は 21118 です。接続する前に、待ち受け状態を確認します。

ss -tlnp | grep 21118

その後、ID ではなく、接続先ピアの VPN アドレスへ接続します。RustDesk の FAQ によると、このモードの接続は暗号化されません。そのため、トンネル内でのみ使用し、オープンインターネット経由では決して使用しないでください。暗号化を提供するのはトンネルです。

マシンの所有者に応じて選択します。自分が所有していないマシンを管理する場合や、VPN クライアントを決してインストールしない利用者をサポートする場合は、自己ホスト型の hbbs と hbbr が適しています。相手側で必要なのは ID とパスワードだけだからです。すべてのマシンを自分が所有しており、各マシンで暗号鍵を扱える場合は、メッシュ VPN と直接 IP アクセスが適しています。WireGuard と Tailscale の比較では、このメッシュを構築する一般的な 2 つの方法を説明しています。Linux VPS でリモートデスクトップを実行するでは、画面を表示したいマシン自体がサーバーである場合について説明しています。

FAQ

すべての RustDesk セッションは自分のリレーを経由しますか?

いいえ。hbbs はまず、各クライアントの前段にある NAT を通過するホールパンチングを使い、2 台のクライアントへの直接接続を試みます。直接接続に失敗したセッションだけが hbbr にフォールバックするため、帯域幅を消費するのもそのセッションだけです。例外は hbbs の ALWAYS_USE_RELAY=Y です。これは直接経路が利用可能かどうかに関係なく、すべてのセッションを hbbr 経由にします。Compose ファイルでこの変数を設定すると、すべてのセッションの全データが転送量の課金対象になります。

RustDesk サーバーキーはどこに保存されますか。紛失した場合はどうなりますか?

hbbs は初回起動時に、作業ディレクトリ内へ id_ed25519 と id_ed25519.pub を生成します。公式イメージでは、そのディレクトリは /root です。そのため、上記のボリュームマウントを使用すると、ファイルはホスト上の ./data に現れます。両方のファイルをサーバー外へバックアップしてください。紛失すると、次回起動時に hbbs が新しいキーペアを生成します。古い公開キーを保持しているすべてのクライアントは拒否されます。復旧するには、すべてのクライアントの Key フィールドを手動で編集するしかありません。

自己ホスト RustDesk サーバーで開放する必要があるポートはどれですか?

TCP 21115、21116、21117、および UDP 21116 です。hbbs は NAT タイプのテストに 21115 を使用します。また、UDP 経由の ID 登録とハートビート、および TCP 経由の登録とホールパンチングに 21116 を使用します。hbbr はリレーに 21117 を使用します。TCP 21118 と 21119 はブラウザクライアント用の WebSocket ポートです。使用しない場合は閉じておいてください。TCP 21114 は Pro HTTP API サーバー用であり、オープンソース版では必要ありません。

自己ホストの RustDesk リレーを第三者が使用できますか?

はい。デフォルト設定の hbbr を実行している場合は使用できます。RustDesk のドキュメントによると、空のキーを設定すると、一致するキーを持たないクライアントでもリレーを使用できます。そのため、ホスト名とポート 21117 を知っている第三者は、あなたのサーバー経由でトラフィックを送信できます。hbbr を -k _ 付きで実行し、共有 ./data ボリュームから hbbs と同じキーペアを読み込ませてください。これにより、あなたの公開キーを設定したクライアントだけが、あなたのサーバー経由でリレーできます。