SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor

Linux VPSのリモートデスクトップ構築方法

Linux VPSでXFCEの実デスクトップをxrdpで動かす方法を解説します。TCP 3389を公開せずSSH tunnelで接続し、RustDeskとの違いも比較します。

Linux VPS でいうリモートデスクトップの実際の意味

「Linux VPS のリモートデスクトップ」で検索すると、異なる 2 種類の製品が見つかります。選択を誤ると、半日を費やすことになります。1 つ目は、リモートアクセスの仲介サーバーです。RustDesk の self-hosted server が代表例です。これは、ノート PC と自宅の PC など、すでに所有している 2 台のマシン間でセッションを中継します。レンタルしたサーバー上でデスクトップは描画されません。2 台の接続先を互いに通知し、直接接続できない場合にパケットを転送します。2 つ目は、レンタルしたサーバー上で実際にグラフィカルデスクトップを実行する方式です。データセンターでピクセルが描画され、その画面がストリーミングされます。これが xrdp、VNC(virtual network computing)、またはコンテナワークスペースです。

この 2 つは、1 つの質問で区別できます。これが動作した後、マウスポインターはどこにあるでしょうか。すでに所有しているマシン上に置きたいなら、仲介サーバーが必要です。VPS 自体で操作したいなら、VPS 上のデスクトップが必要です。以下では後者を中心に説明します。多くのガイドが省略しているのが、このケースだからです。

業務に適した選択肢

  • 独自の relay を使用する RustDesk。 他者が運用する公開 rendezvous server を経由せずにセッションを保護できます。key pair を自分で管理するためです。ただし、制御対象のマシン自体は保護しません。保護対象は、client をインストールした PC と、その PC に設定された password のままです。
  • SSH tunnel または VPN 経由の xrdp。 TCP 3389 に対するインターネット全体からの継続的なスキャンと、RDP のログイン画面に対する password guessing から保護できます。その port がインターネットに公開されないためです。ただし、すでに tunnel に接続できる攻撃者から、脆弱な account password を保護することはできません。
  • 同じ tunnel 経由の VNC。 RDP より古く単純な protocol を使用し、切断後も維持される desktop session を利用できます。単独では何も保護しません。セキュリティ対策はすべて tunnel が担うため、公開 port で VNC だけを実行する構成は、ここで最も悪い選択肢です。
  • Webtop や Kasm などの container workspace。 破棄して再構築できる container 内で browser または完全な desktop を利用できます。その browser がアクセスする対象から実機を保護できます。ただし、host は保護しません。これらの image は広範な権限で実行され、内部に passwordless の sudo があるためです。したがって、container を悪意のある workload に対する境界として信頼すべきではありません。

Ubuntu 24.04 に xrdp と XFCE をインストールする

VPS のサーバーイメージには、グラフィカルデスクトップが含まれていません。まずデスクトップをインストールし、次に RDP(remote desktop protocol)を使用するオープンソースサーバーの xrdp をインストールします。これは Windows クライアントが使用するプロトコルと同じです。軽量なデスクトップを選ぶ場合、通常は XFCE を使用します。

sudo apt update
sudo apt install -y xrdp xorgxrdp xfce4 xfce4-goodies dbus-x11
systemctl is-active xrdp

2026 年 8 月時点で、Ubuntu 24.04 の universe コンポーネントには xrdp 0.9.24 と xorgxrdp が含まれています。xorgxrdp は推奨パッケージにすぎませんが、名前を指定してインストールしてください。これは xrdp が新しいセッション用に起動する X サーバーのバックエンドです。これがないと、ログイン画面でパスワードを受け付けた後、再びログイン画面に戻ります。

次に、セッションで起動するデスクトップを指定します。xrdp は /etc/xrdp/startwm.sh を実行し、このファイルが存在する場合は ~/.xsession を実行します。

echo "xfce4-session" > ~/.xsession
chmod 644 ~/.xsession

最後に、xrdp にはクライアントへ提供する TLS(transport layer security)キーを読み取る権限が必要です。このファイルのモードは 640 で、所有グループは ssl-cert です。

ls -l /etc/ssl/private/ssl-cert-snakeoil.key
id xrdp

一覧には -rw-r----- 1 root ssl-cert と表示されます。id xrdp のグループ一覧に ssl-cert が表示されない場合は、sudo adduser xrdp ssl-cert を実行してから sudo systemctl restart xrdp を実行します。これを行わないと xrdp はキーを開けません。また、/var/log/xrdp.log には snakeoil のファイル名を含む行で、この失敗が記録されます。

インターネットに port 3389 を開放してはいけない理由

TCP 3389 はインターネット上のあらゆる場所から継続的にスキャンされています。RDP のログイン画面は、すべてのパスワード試行に応答します。開放しないでください。代わりに xrdp を loopback address に bind し、信頼できる tunnel を経由して接続します。

/etc/xrdp/xrdp.ini を編集し、[Globals] section の listener を変更します。

[Globals]
port=tcp://.:3389

配布されているファイルには、この構文の説明がコメントとして記載されています。tcp://.:3389 は 127.0.0.1:3389 を、tcp://:3389 はすべての interface を意味します。ここで入力を誤ると、service がすべての address で待ち受ける状態が気付かないまま残るため、restart して確認してください。

sudo systemctl restart xrdp
ss -tlnp | grep 3389

必要なのは 127.0.0.1:3389 です。0.0.0.0:3389 と表示される場合、xrdp は編集内容を無視しています。通常は、ファイルの下側にある別の section heading の下に行を記述しています。

次に、自分のマシンから tunnel を開きます。

ssh -N -L 3389:127.0.0.1:3389 you@vps.example.com

-N は「接続を開くが、command は実行しない」という意味です。そのため、session は port の転送だけに使用されます。その terminal は開いたままにし、RDP client から 127.0.0.1:3389 に接続します。Linux client では FreeRDP 3 を使用します。Ubuntu 24.04 での binary 名は xfreerdp3 です。

sudo apt install -y freerdp3-x11
xfreerdp3 /v:127.0.0.1:3389 /u:you /dynamic-resolution +clipboard /sound

Windows では組み込みの mstsc を使用し、computer として 127.0.0.1 を入力します。FreeRDP は初回接続時に certificate を信頼するか確認し、Do you trust the above certificate? (Y/T/N) と表示します。これは self-signed の snakeoil certificate を使用しているためで、想定された動作です。

ssh が bind [127.0.0.1]:3389: Address already in use と応答する場合、自分のマシン上ですでに何かが 3389 を使用しています。ssh -N -L 13389:127.0.0.1:3389 you@vps.example.com で local end を変更し、127.0.0.1:13389 に接続してください。

1 人につき 1 本の tunnel を使う方法は手間がかかります。チームで使用する場合は、private network のほうが適しています。self-hosted WireGuard VPN の背後にサーバーを置き、tunnel address として 10.8.0.1 を割り当て、xrdp が VPN 内部でのみ応答するよう port=tcp://10.8.0.1:3389 を設定します。いずれの場合も、3389 の firewall rule は完全に削除してください。現在の rule で何が許可されているか不明な場合は、VPS の ufw firewall の基本 から確認し、接続後ではなく接続前に調べてください。

2 GB の VPS でリモートデスクトップが使用する RAM 量

選択するデスクトップによって、2 GB プランを快適に使えるか、実用にならないかが決まります。以下の数値は、Ubuntu 24.04 へのログイン直後に使用中となるメモリの一般的な値を丸めたものです。ご利用のマシンで測定した値ではなく、公表されている比較結果に基づいています。接続直後に free -m を実行して、ご自身の環境で測定してください。

ChartTypical memory in use after login, Ubuntu 24.04 (published figures)
The data behind this chart
[
  {
    "label": "LXQt",
    "idle_ram_mb": 300
  },
  {
    "label": "XFCE",
    "idle_ram_mb": 400
  },
  {
    "label": "MATE",
    "idle_ram_mb": 500
  },
  {
    "label": "KDE Plasma",
    "idle_ram_mb": 800
  },
  {
    "label": "GNOME",
    "idle_ram_mb": "1,200"
  }
]

これら 5 種類のデスクトップでは、使用量の差が重要です。LXQt は約 300 MB、XFCE は約 400 MB なので、どちらも 2 GB の環境でブラウザーを動かす余裕が残ります。GNOME はウィンドウを 1 つも開いていない状態で約 1,200 MB を必要とします。2 GB では、残りのメモリをブラウザーとデスクトップが奪い合うことになります。

本当の負荷はデスクトップシェルではなく、ブラウザーです。最新のブラウザーは、アクティブなタブ 1 つあたり 150~400 MB 程度を使用します。そのため、XFCE を実行する 2 GB の VPS では、数個のタブを開くとスワップが始まります。プロセスが強制終了されるのではなく、システムの動作が遅くなるように、スワップを追加します。sudo fallocate -l 2G /swapfile、続いて sudo chmod 600 /swapfilesudo mkswap /swapfilesudo swapon /swapfile を実行し、再起動後も維持されるように /etc/fstab に対応する行を追加します。何かが警告なしに消えた場合は、dmesg | grep -i "killed process" を実行してください。その行は、カーネルの out-of-memory killer がプロセスを終了したことを示します。通常はブラウザーが終了対象になります。

もう 1 つの制限は CPU で、こちらは過小評価しやすい要素です。VPS には GPU がないため、X は llvmpipe を介したソフトウェアレンダリングにフォールバックします。つまり、すべてのピクセルを CPU で描画します。負荷の高いページのスクロールや動画の再生では、CPU 使用率がそのまま上昇し、マシンがフリーズするのではなくフレームレートが低下します。これは、VPS でゲームを実行できるかを考えた場合に直面する制限と同じです。3D の用途では答えは「できません」であり、その理由もまさにこれです。

xrdp セッションのサウンドとクリップボード

Ubuntu 24.04 はオーディオに PipeWire を使用します。一方、xrdp のサウンドリダイレクトは PulseAudio 向けに実装されているため、新規インストール直後は映像だけが機能し、音声は出ません。Ubuntu にはこのためのブリッジが用意されています。

sudo apt install -y pipewire-module-xrdp pulseaudio-utils alsa-utils

RDP セッションから完全にログアウトして、もう一度ログインします。セッションの開始時にモジュールが読み込まれるためです。再接続だけでは不十分です。次に、セッション内で以下を確認します。

pactl list short sinks
speaker-test -c 2 -t wav -l 1

名前に xrdp を含むシンクが表示され、クライアントからテスト音が聞こえるはずです。xrdp シンクがない場合、このセッションにモジュールが読み込まれていません。クライアント側でも音声を要求する必要があります。xfreerdp3/sound フラグを指定するか、Windows クライアントの「ローカル リソース」にある「リモート オーディオ」設定を有効にします。

xrdp-chansrv がセッションで実行されていれば、テキストのクリップボードは双方向で機能します。xrdp がこのプロセスを起動するため、pgrep -a xrdp-chansrv で確認できます。セッションの途中でコピーと貼り付けが機能しなくなった場合、そのプロセスが終了しています。再接続するとプロセスが再起動します。テキストではなくファイルをコピーする機能は、ドライブリダイレクトという別のチャネルです。xfreerdp3 上の /drive:home,/home/you により、ローカルフォルダーがリモートセッションにマウントされます。

polkit のポップアップと、その他の初回ログイン時の失敗

初回ログイン時に最もよくある問題は、Authentication is required to create a color managed device と表示されるダイアログです。原因は明確です。colord サービスは polkit に権限を要求します。polkit は、その操作をローカルに着席していると判断したセッションに対してのみ、確認なしで許可します。RDP セッションは着席セッションではないため、polkit はパスワードの入力を求めます。Ubuntu 24.04 には polkit 124 が同梱されています。このバージョンでは従来のローカル authority ファイル .pkla が削除されています。そのため、/etc/polkit-1/localauthority/50-local.d/45-allow-colord.pkla を作成するよう案内する手順は、24.04 ではまったく効果がありません。代わりに JavaScript ルールを作成してください。

/* /etc/polkit-1/rules.d/45-allow-colord.rules */
polkit.addRule(function(action, subject) {
    if (action.id.indexOf("org.freedesktop.color-manager.") === 0 &&
        subject.isInGroup("sudo")) {
        return polkit.Result.YES;
    }
});

sudo systemctl restart polkit を実行してから再接続します。症状から判断できる、その他の 2 つの失敗も確認しておきます。

ログインボックスにパスワードを入力すると、すぐに同じ画面へ戻る。 セッションは開始しましたが、終了しています。まず /var/log/xrdp-sesman.log を確認し、次にホームディレクトリ内の ~/.xsession-errors を確認します。xorgxrdp がない場合、インストールされていないデスクトップを指定する ~/.xsession がある場合、書き込みできないホームディレクトリを使用している場合、またはディスク容量が満杯の場合は、いずれもこの症状になります。

接続すると、X カーソルが表示された灰色の画面になる。 X は起動しましたが、デスクトップは起動していません。これも ~/.xsession が原因です。SSH 経由で xfce4-session を手動実行し、表示されるエラーを確認してください。

セルフホスト型 RustDesk サーバーの役割

RustDesk は 2 つのプロセスに分かれています。hbbs はクライアントが登録する ID およびランデブーサーバーです。hbbr は、直接のピアツーピア接続に失敗した場合にセッションを中継します。どちらもデスクトップ環境は実行しません。両方とも 1 つのイメージに含まれています。以下は、リレー先アドレスを自分のホスト名に変更した、プロジェクトが公開している compose ファイルです。

services:
  hbbs:
    container_name: hbbs
    image: rustdesk/rustdesk-server:latest
    command: hbbs -r rustdesk.example.com:21117
    ports:
      - 21115:21115
      - 21116:21116
      - 21116:21116/udp
      - 21118:21118
    volumes:
      - ./data:/root
    restart: unless-stopped
  hbbr:
    container_name: hbbr
    image: rustdesk/rustdesk-server:latest
    command: hbbr
    ports:
      - 21117:21117
      - 21119:21119
    volumes:
      - ./data:/root
    restart: unless-stopped

起動したら、初回起動時にサーバーが生成した公開鍵を確認します。

sudo docker compose up -d
sudo cat ./data/id_ed25519.pub

すべてのクライアントで、RustDesk クライアントの Network 設定にホスト名と公開鍵を入力する必要があります。対応する秘密鍵は ./data/id_ed25519 に保存されます。データディレクトリを削除すると、サーバーは新しい鍵ペアを生成します。その場合、すべてのクライアントで新しい鍵を設定し直す必要があります。このディレクトリをバックアップしてください。

ファイアウォールでは、これらのポートへの直接接続を許可する必要があります。hbbs は TCP 21115、21116、21118 と UDP 21116 を使用します。hbbr は TCP 21117 と 21119 を使用します。

sudo ufw allow 21115/tcp
sudo ufw allow 21116/tcp
sudo ufw allow 21116/udp
sudo ufw allow 21117/tcp
sudo ufw allow 21118/tcp
sudo ufw allow 21119/tcp

Nginx や Traefik の背後で RustDesk が動作しない理由

すべての TLS 終端を 1 台のリバースプロキシで処理している環境では、この構成を試して失敗することがあります。hbbs と hbbr は HTTP ではなく、独自のバイナリプロトコルを TCP と UDP で使用します。ルーティングに使える Host ヘッダーがなく、検査できる HTTP リクエストもありません。そのため、nginx の server ブロックや Traefik の HTTP ルーターには照合対象がありません。21116 の UDP リスナーは、どの層でも HTTP として動作していません。

動作する方法は 2 つあります。nginx では stream ブロックを使って TCP ポートを転送できます。これは通常の意味でのリバースプロキシではなく、単純なレイヤー 4 転送です。また、21118 と 21119 は RustDesk Web クライアントが使用する WebSocket を処理します。これは通常の HTTP なので、この 2 つのポートはプロキシの背後に配置できます。その場合は、21118 と 21119 にアクセスできるのをプロキシだけに制限するファイアウォールルールを追加してください。hbbs は WebSocket 接続の X-Real-IP ヘッダーを信頼し、実際のクライアントアドレスを判断するためです。

コンテナ内の使い捨てブラウザー

必要なのが、IP アドレスが変わらず、自分のマシンから隔離されたクリーンなブラウザーだけという場合があります。コンテナのワークスペースなら、インストールするソフトウェアを大幅に減らして実現できます。LinuxServer の Webtop は軽量な選択肢です。

services:
  webtop:
    image: lscr.io/linuxserver/webtop:latest
    container_name: webtop
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
    volumes:
      - /path/to/data:/config
    ports:
      - 127.0.0.1:3000:3000
      - 127.0.0.1:3001:3001
    shm_size: "1gb"
    restart: unless-stopped

3000 番ポートは HTTP、3001 番ポートは HTTPS を提供します。RDP クライアントを使わず、ブラウザーのタブからデスクトップに接続できます。イメージタグでは、複数のベースディストリビューション上の XFCE、KDE、MATE、i3 が用意されています。プロジェクトのドキュメントでは、リスクを明確に説明しています。このコンテナはホストに対する特権アクセスを持ち、パスワードなしで sudo を実行できるターミナルを含みます。そのため、保護されていない状態でインターネットに公開してはいけません。これが、上記のポートをすべてのアドレスに公開せず、127.0.0.1 にバインドする理由です。xrdp で使用したものと同じ SSH トンネルまたは VPN 経由で接続してください。

Kasm Workspaces も同じ考え方ですが、規模が大きく、Web コンソール、ユーザーアカウント、セッション終了時にリセットされるセッションごとのコンテナを備えています。小規模な VPS より多くのリソースが必要です。2026 年 8 月時点で、ドキュメントに記載された最小要件は CPU 2 コア、メモリ 4 GB、SSD 50 GB です。さらに、各ユーザーセッションではデフォルトで CPU 2 コアと 2768 MB が必要です。2 GB プランでは実行できません。インストールはダウンロードとスクリプトの実行だけで完了します。

cd /tmp
curl -O https://kasm-static-content.s3.amazonaws.com/kasm_release_1.17.0.7f020d.tar.gz
tar -xf kasm_release_1.17.0.7f020d.tar.gz
sudo bash kasm_release/install.sh

VNC と、現在も適する用途

VNC は描画コマンドではなくフレームバッファの更新を送信するため、低速なリンクでは RDP より重く感じられ、音声チャネルもありません。VNC が適するのは、切断後もデスクトップセッションを実行し続け、戻ったときに同じセッションを再開したい場合です。TigerVNC はこれに対応しています。vncserver -localhost yes :1 は Xvnc を TCP 5901 の 127.0.0.1 にバインドし、それ以外からの接続を拒否するため、ssh -N -L 5901:127.0.0.1:5901 you@vps.example.com を使用して xrdp と同じ方法でトンネルします。VNC ポートを公開してはいけません。ほとんどの VNC サーバーはハンドシェイク中のパスワードだけを保護し、その後の通信は保護しません。そのため、公開ポートではセッションの内容がネットワーク上で読み取られます。

VPS はデスクトップとして適していますか?

日常的に使う環境としては適していません。理由がいくつもあります。GPU がないため、すべての描画を CPU が処理します。キー入力のたびにネットワークの往復を待つ必要があり、SSH では問題ない 40 ms のレイテンシーでも、テキストエディターでは遅延として感じられます。映像は、サイト側と RDP エンコーダーによって 2 回圧縮されます。ファイルは自分が保持していないディスクに保存され、デスクトップを頻繁に使うと、Web サーバー向けに設定された月間帯域幅の上限を消費します。

一時的に使い捨てるマシンとしては非常に適しています。その理由は、同じ特性にあります。IP アドレスは固定され、データセンターに割り当てられています。サービスから一貫したアドレスとして認識させたい場合に適しています。マシンはイメージから数分で再構築できるため、セッションで悪意のあるものを取得しても、失うものはありません。実際のハードウェアから分離されており、ノート PC を閉じても動作し続けます。時間単位の課金なら、使い捨てのデスクトップを安価に利用できます。

その VPS の用途をまだ決めていない場合は、デスクトップをインストールする前に、VPS の用途に関する実用的な一覧を読む価値があります。デスクトップが必要な理由が Windows アプリケーション 1 つだけであれば、まず Linux と Windows Server の実際の違いと比較してください。ライセンスによって答えのコストが変わるためです。

FAQ

2 GB の VPS でリモートデスクトップを実行できますか?

はい。軽量なデスクトップ環境を使用してください。XFCE または LXQt はログイン後におよそ 300 から 400 MB を使用するため、タブを数個開いたブラウザーを動かす余裕が残ります。2 GB で GNOME または KDE Plasma を使用すると、アプリケーション用のメモリがほとんど残りません。2 GB の swap ファイルを追加すると、メモリ圧迫時にプロセスが強制終了される代わりに、マシンの動作が遅くなります。何もメッセージを表示せずにプロセスが消えた場合は、カーネルの out-of-memory killer について dmesg | grep -i "killed process" を確認してください。

VPS のファイアウォールでポート 3389 を開くべきですか?

いいえ。TCP 3389 は常時スキャンされており、RDP のログイン画面を公開するとパスワード推測攻撃を招きます。/etc/xrdp/xrdp.iniport=tcp://.:3389 を設定し、xrdp が 127.0.0.1 だけで待ち受けるようにしてください。ss -tlnp | grep 3389 で設定を確認し、ssh -N -L 3389:127.0.0.1:3389 you@vps.example.com で接続します。1 人または 2 人を超える利用者がいる場合は、loopback ではなく WireGuard のアドレスに xrdp をバインドしてください。

xrdp が「Authentication is required to create a color managed device」と表示するのはなぜですか?

colord サービスは polkit に権限を要求します。polkit がその操作を無言で許可するのは、ローカルの画面に着席しているセッションだけです。RDP セッションは着席セッションではないため、ログインするたびにパスワードを要求されます。Ubuntu 24.04 では、従来の .pkla による修正は機能しません。polkit 124 がローカル authority ファイルを廃止したためです。アクション ID が org.freedesktop.color-manager. で始まる場合に polkit.Result.YES を返す JavaScript ルールを /etc/polkit-1/rules.d/45-allow-colord.rules に作成し、その後 sudo systemctl restart polkit を実行してください。

self-hosted RustDesk サーバーを nginx または Traefik の背後に配置できますか?

メインサービスは配置できません。hbbs と hbbr は HTTP ではなく独自のバイナリプロトコルを使用するため、ルーティングに使用できる Host ヘッダーがありません。また、UDP 21116 は HTTP プロキシを通過できません。ファイアウォールで TCP 21115 から 21119 と UDP 21116 を開き、クライアントから直接接続させてください。Web クライアントが使用する websocket ポート 21118 と 21119 は HTTP なので、プロキシの背後に配置できます。その場合は、プロキシからの接続だけを許可するようファイアウォールで制限してください。これらの接続では hbbs が X-Real-IP を信頼するためです。

xrdp セッションで音声が出ないのはなぜですか?

Ubuntu 24.04 は PipeWire を使用します。一方、xrdp の音声リダイレクトは PulseAudio 向けに作られているため、ブリッジをインストールするまで音声が利用できません。sudo apt install -y pipewire-module-xrdp を実行し、セッションから完全にログアウトしてから再度ログインしてください。モジュールはセッション開始時に読み込まれるため、再接続だけでは読み込まれません。pactl list short sinks で xrdp という名前の sink があるか確認してください。クライアントが音声を要求する設定になっていることも確認します。これは xfreerdp3/sound フラグ、または Windows クライアントの「Remote audio」に該当します。

#remote-desktop#xrdp#rustdesk#vnc#self-hosting