リモートボックスでのエージェント型コーディング環境の構築
Tailscale、tmux、mosh、systemdでClaude Codeをリモートボックスに設定し、SSH鍵、秘密情報、非公開アクセスの安全策も解説します。
リモートボックスでClaude Codeを実行するための最小構成スタックは、Linux VPSまたは常時稼働マシン、ポートフォワーディングや動的DNSを必要としないプライベートWireGuardメッシュを提供するTailscale、切断後もセッションを維持するtmux、そして接続レイヤーとしてのmoshまたはSSHです。いずれも無料で、相互に組み合わせ可能であり、今月登場したばかりのラッパーツールが廃れた後も継続して使用できます。本ガイドでは、既存の解説記事が見落としがちなユースケース、すなわちクラウドVPSや手持ちのマシン上でコーディングエージェントを稼働させ、セキュリティを強化した上でラップトップやスマートフォンからリモート操作するシナリオを、このスタック全体にわたって順を追って説明します。
解決すべき問題は「永続性」です。コーディングエージェントをローカルで実行中にラップトップを閉じると、セッションが終了してしまいます。リモートボックスを使えば、切断をまたいでエージェントを稼働し続けられ、マネージドプラットフォームと比べてコストを把握しやすく、どこからでも作業を操作できます。ただし、あまり語られていない落とし穴があります。シェルアクセスとAPIキーを持つエージェントが稼働するボックスは、深刻な攻撃対象になり得るということです。そのため、本ガイドではセキュリティを後付けにせず、最初から中心に据えて解説します。
重要なポイント
- 読者がよく混同する2つの異なる目的があります。Claude Codeのような CLIエージェントをアタッチ・デタッチできる永続セッションで実行すること(tmuxパターン)と、エージェントを常時稼働のHTTPサービスとしてホストすること(systemdパターン)です。それぞれ異なるセットアップとセキュリティ体制が必要です。
- TailscaleはデバイスをWireGuard暗号化メッシュで接続します。リモートボックスには安定した
100.x.x.xアドレスが割り当てられ、ファイアウォールポートを開放したり動的DNSを設定したりすることなく、認証済みのデバイスからアクセスできます。 - コーディングエージェントが稼働するリモートボックスには、シェルアクセス、APIキー、リポジトリ認証情報が存在します。パブリックVPS上でエージェントのポートを
0.0.0.0にバインドすると、動作確認のためのわずかな時間であっても、これら3つすべてが危険にさらされます。 - systemdのユニットファイルの
Environment=行にAPIキーを記述してはいけません。systemctl showの出力に表示されてしまうためです。EnvironmentFile=を使用してキーをユニットファイルから分離し、真のシークレット保護が必要な場合はLoadCredential=を活用してください。 - Claude Codeにはネイティブのリモートコントロールとクラウドリモートセッション機能が搭載されていますが、いずれも単一セッションであり、稼働中のプロセスに依存します。常時稼働、ヘッドレス、またはマルチプロジェクトの構成には、DIYスタックが適しています。
リモートボックスを使う理由:DIYと代替手段の比較
リモートボックスが有効なのは、切断をまたいで稼働し、無人で動作し、どのデバイスからもアクセスできるコーディングエージェントが必要な場合です。プラットフォームのユーザーごとの料金を支払うことなく、サンドボックスの制限を受けずに運用できます。その代わり、セキュリティ、稼働率、パッチ適用はすべて自己責任となります。SSHとGitに慣れた開発者にとって、このトレードオフは通常、十分に見合うものです。
何かを構築する前に、3つのアプローチのどれが自分に合っているかを判断しましょう。2026年初頭に状況が変わり、「Claude Codeをリモートで使うにはtmuxとSSHが必要」という従来の見方は今や不完全です。
| アプローチ | 概要 | 最適なユースケース | 制限事項 |
|---|---|---|---|
| ネイティブリモートコントロール / リモートセッション | Claude Code組み込みのリモート機能。スマートフォンやブラウザからのアウトバウンドのみのHTTPS制御と、Anthropicがホストするクラウドセッション | インフラ不要で単一セッションを操作したい場合 | 単一セッション限定。稼働中のプロセスに依存。他社のプラットフォームで動作 |
| DIYリモートボックス | tmuxまたはsystemd下でエージェントを実行する自前のVPSまたは手持ちのマシン | 常時稼働、ヘッドレス、マルチプロジェクトの作業をエンドツーエンドで自己管理したい場合 | セキュリティと稼働率は自己責任 |
| マネージドエージェントプラットフォーム | 並列エージェントをオーケストレーションするホスト型製品 | 運用作業なしで洗練されたマージツールを求めるチーム | ベンダーロックイン。継続的なコスト |
Anthropicは2026年初頭(2026年半ば時点でCLI v2.1.x)にネイティブのリモートコントロールをリサーチプレビューとして、クラウドリモートセッションを正式リリースしました。リモートコントロールはアウトバウンドのみのHTTPSを使用し、インバウンドポートを開放せずにスマートフォンからセッションを操作できます。実用的な機能ですが、単一セッション限定であり、起動したターミナルが終了するとセッションも終了します。Claude Code自体はインタラクティブセッション用のバックグラウンドデーモンを持たないCLIツールとして動作します。ヘッドレスデーモンモードに関するオープンなフィーチャーリクエストでも、ターミナルを閉じるとセッションが終了することが確認されています。常時稼働、ヘッドレス、またはマルチプロジェクトの構成では、耐久性のあるプリミティブを基盤とし、その上に便利なツールを重ねていく必要があります。
マネージドプラットフォームのカテゴリも存在し、資金も豊富ですが、SSHとGitを日常的に使う開発者にとっては、セルフホスト型のボックスの方がより低コストで高い制御性を得られます。本ガイドではDIYの方法を解説します。
2つのパターン:tmux vs. systemd
読者がよく混同する2つの異なる目的があり、それぞれ異なるセットアップが必要です。Claude Codeのような CLIコーディングエージェントをアタッチ・デタッチできるセッションで実行することがtmuxパターンです。エージェントをAPIからアクセスできる常時稼働のHTTPサービスとしてホストすることがsystemdパターンです。この選択を誤ることが、リモートエージェント構成における最も一般的な構造的ミスです。
| tmux(インタラクティブ) | systemd(サービス) | |
|---|---|---|
| ユースケース | リアルタイムで操作するCLIエージェント | 無人で動作するHTTPエージェント |
| クラッシュ時の再起動 | 手動でリアタッチ | Restart=always |
| ログ | セッションのスクロールバック | journalctl -u <service> |
| シークレット | シェル環境変数または.envのsource | EnvironmentFile= / LoadCredential= |
| モバイルアクセス | mosh + tmux attach | リバースプロキシ経由でcurlまたはブラウザ |
エージェントを監視しながら操作したい場合、つまりプロンプトを入力したり、アクションを承認したり、出力を読んだりする場合はtmuxを使用します。エージェントがリクエストを受け付けて人間の操作なしに動作するサービスである場合はsystemdを使用します。Claude Codeをインタラクティブに実行する人の多くはtmuxを必要とし、エージェントをAPIの背後に公開する人の多くはsystemdを必要とします。両方を組み合わせる構成もあります。
Claude Codeをリモートで実行する:標準的な無料スタック
Claude Codeをリモートで実行するための標準的な無料スタックは、Linuxボックス、プライベートネットワークレイヤーとしてのTailscale、接続手段としてのOpenSSHとmosh、そして永続セッションのためのtmuxです。このセクションでは、コピー&ペーストで使えるセットアップ手順を説明します。本番環境として使用する前に、次のセクションのセキュリティ強化を必ず実施してください。
Discover how at OpenReplay.com.
Tailscaleのインストール
Tailscaleはデバイス間にWireGuard暗号化メッシュを構築します。インストールすると、リモートボックスには安定した100.x.x.xアドレスが割り当てられ、ファイアウォールポートの開放、動的DNSの設定、ルーターの設定変更なしに、認証済みのデバイスからアクセスできます。Tailscaleの基盤プロトコルはWireGuardであり、無料のPersonalプランでは2026年4月の料金改定時点で最大6ユーザー、ユーザー所有デバイス数無制限に対応しています。利用前に最新の制限を確認してください。
公式インストールドキュメントに従ってリモートボックスにインストールします。
curl -fsSL https://tailscale.com/install.sh | sh
sudo tailscale up
tailscale upコマンドを実行すると認証URLが表示されます。URLを開いてサインインすると、ボックスがtailnetに参加します。tailscale ip -4を実行して100.x.x.xアドレスを確認してください。ラップトップとスマートフォンにも同様にTailscaleをインストールして同じアカウントで認証すると、3つのデバイスが相互に直接通信できるようになります。
構成が静かに壊れる落とし穴として、実際に遭遇したものを紹介します。moshを使用する予定がある場合は、tailscale up --sshでTailscaleの組み込みSSHサーバーを有効にしないでください。Tailscale SSHはOpenSSHではなくTailscale独自のSSHサーバーを実行します。moshはセッションをブートストラップするためにOpenSSH経由でmosh-serverを実行してその出力を解析する必要がありますが、Tailscale SSHはこれをサポートしていません。moshが接続できるよう、Tailscaleと並行してOpenSSHをインストールして実行し続けてください。
SSHとmoshのセットアップ
SSHはシェルを提供し、moshはIPアドレスの変更やローミングを乗り越えてセッションを維持することで、不安定なモバイル接続でも快適に使えるようにします。moshはセッションのブートストラップに60000〜61000番のUDPポート範囲が到達可能である必要があります(moshドキュメント参照)。Tailscaleメッシュ上では認証済みデバイス間でこの範囲がすでに到達可能なため、ルーターの設定変更は不要です。
サーバーとクライアントの両方にmoshをインストールします。
sudo apt update && sudo apt install -y mosh tmux
ラップトップからTailscaleアドレスを使って接続します。
mosh youruser@100.x.x.x
moshの接続に失敗した場合は、ssh youruser@100.x.x.xでボックスへの到達性を確認し、OpenSSH(Tailscale SSHではない)が応答しているかどうかを確認してください。
永続的なtmuxセッションの作成
tmuxは切断後もエージェントを稼働させ続けるためのものです。セッションを開始し、その中でClaude Codeを実行してデタッチすると、エージェントは動作し続けます。後でどのデバイスからでもリアタッチして状況を確認したり操作したりできます。
tmuxセッションにはツール名ではなくプロジェクト名を付けましょう。tmux new-session -s claudeではなくtmux new-session -s myprojectを使用します。3つのリポジトリで3つのエージェントを実行している場合、tmux lsでどのセッションがどれかを判別できる必要があります。
tmux new-session -s myproject
# セッション内で:
cd ~/code/myproject
claude
# Ctrl-b の後 d でデタッチ
-sフラグはセッションに名前を付けます。どこからでもtmux attach -t myprojectでリアタッチでき、tmux lsで実行中のすべてのセッションを一覧表示できます。このデタッチとリアタッチのサイクルが、インタラクティブなリモートエージェントの基本的な操作ループです。ラップトップを閉じ、mosh経由でスマートフォンからリアタッチし、エージェントの作業内容を確認して次の指示を与えます。
セキュリティのベースライン
コーディングエージェントが稼働するリモートボックスは、価値の高い攻撃対象です。シェルアクセス、APIキー、そして多くの場合リポジトリ認証情報を保持しています。パブリックVPS上でエージェントのポートを0.0.0.0にバインドすると、動作確認のためのわずかな時間であっても、これら3つすべてが危険にさらされます。APIキーなどの重要な情報を扱う前に、ボックスを必ず強化してください。このセクションは省略できません。
SSHキー認証のみを許可
パスワード認証を無効にして、自分が保持するキーのみでログインできるようにします。/etc/ssh/sshd_configを編集して以下を設定します。
PasswordAuthentication no
PermitRootLogin no
PasswordAuthentication noはパスワードログインを無効にし、PermitRootLogin noはrootへの直接SSHをブロックします。いずれもsshd_configマニュアルに記載されています。よくあるミスとして、誤ったファイルを編集してしまうことがあります。これらの設定はクライアント設定ファイルではなく/etc/ssh/sshd_configに記述します。sudo systemctl restart sshで適用してください。タイポによるロックアウトを防ぐため、現在のセッションを閉じる前に別のセッションでキー認証が機能することを確認してください。
プライベートメッシュをプライベートに保つ
Tailscaleのメッシュはすでに認証済みですが、Tailscale ACLを使用してどのデバイスがどのポートにアクセスできるかをさらに制限できます。ACLポリシーはタグ付きデバイス間のトラフィックを制限します。たとえば、ラップトップとスマートフォンのみがエージェントボックスにアクセスでき、tailnet上の他のデバイスはアクセスできないように設定できます。単一ユーザーの構成では、デフォルトの「tailnet内のすべてを許可」で十分です。他のユーザーや信頼できないデバイスがネットワークを共有する場合はACLを追加してください。
エージェントを0.0.0.0にバインドしない
ローカルバインドのサービスを動作確認する際は、一時的に0.0.0.0にバインドする代わりに、サーバー自体からcurl http://127.0.0.1:9000/healthを使用してください。ポート9000をブロックするファイアウォールルールがないVPSでは、この一行の変更でプロセスが実行されている間ずっとエージェントがパブリックインターネットに公開されてしまいます。127.0.0.1にバインドし、Tailscaleまたはリバースプロキシでサービスにアクセスしてください。直接アクセスは避けてください。
ユニットファイルにシークレットを記述しない
systemdユニットファイルのEnvironment=行にAPIキーを記述してはいけません。systemctl showの出力に表示されてしまいます。systemd.execドキュメントに従い、EnvironmentFile=/etc/myagent/secrets.envを使用して値をユニットファイルとsystemctl showから分離してください。ファイルのアクセス権を適切に設定します。
sudo mkdir -p /etc/myagent
sudo chmod 640 /etc/myagent/secrets.env
sudo chown root:myagent /etc/myagent/secrets.env
この設定で得られる保護範囲を正確に理解しておきましょう。EnvironmentFile=はシークレットをユニットファイルとsystemctl showから分離しますが、一度ロードされると、値は稼働中のプロセス環境とD-Bus経由で読み取り可能な状態のままです。真のシークレット保護には、systemdのクレデンシャルガイドに記載されているsystemdのLoadCredential=を使用してください。これはプロセス環境ではなく制限されたディレクトリを通じてクレデンシャルを渡します。
サービスエージェントを常時稼働させる:systemdユニット
インタラクティブなセッションではなく常時稼働のHTTPサービスとしてエージェントを実行する場合は、127.0.0.1にバインドしてRestart=alwaysを設定したsystemdユニットを使用します。これがsystemdパターンです。サービスは起動時に開始され、クラッシュ時に再起動し、ジャーナルにログを記録し、パブリックポートに直接アクセスされることはありません。EnvironmentFile=は長年にわたるsystemdのコアディレクティブであり、systemd.execドキュメントに記載されているとおり、現在のすべてのsystemdリリースで利用可能です。
/etc/systemd/system/my-agent.serviceを作成します。
[Unit]
Description=My Agent Service
After=network.target
[Service]
User=myagent
Group=myagent
WorkingDirectory=/home/myagent/app
EnvironmentFile=/etc/myagent/secrets.env
ExecStart=/home/myagent/app/venv/bin/uvicorn main:app --host 127.0.0.1 --port 9000
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
各ディレクティブには存在する理由があります。After=network.targetはネットワークが利用可能になるまで待機します。専用のUser/Groupで実行することで、エージェントが侵害された場合の影響範囲を限定します。EnvironmentFile=はアクセス権が制限されたファイルからシークレットをロードします。ExecStartはプロジェクトの仮想環境から直接サーバーを実行します。ラッパースクリプトは使用せず、127.0.0.1にバインドしてポートが外部から到達できないようにします。Restart=alwaysとRestartSec=5を組み合わせることで、クラッシュから5秒後にサービスを再起動します。
有効化して起動します。
sudo systemctl daemon-reload
sudo systemctl enable --now my-agent
sudo systemctl status my-agent
サービスを安全に公開するには、localhostバインドのポートの前にリバースプロキシを配置します。nginxのproxy_passで127.0.0.1に転送することで、アップストリームを外部から直接アクセスできないようにしながら、エッジでTLSを終端します。
server {
listen 443 ssl;
server_name agent.example.com;
ssl_certificate /etc/letsencrypt/live/agent.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/agent.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:9000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
証明書はCertbotでプロビジョニングしてください。Let’s Encryptの発行と更新を自動化できます。単一ユーザーの構成では、パブリックホスト名が不要な場合も多くあります。認証済みデバイスからTailscale経由で100.x.x.x:9000にアクセスすることで、パブリックな攻撃面を完全に回避できます。
モバイルからボックスにアクセスする
スマートフォンからリモートエージェントにアクセスする方法は、ラップトップからアクセスする方法と同じです。Tailscale経由で、ターミナルクライアントまたはブラウザターミナルを使用します。このツール環境は2026年半ば時点で急速に変化しています。これらはオプションの拡張機能として扱い、基盤となるインフラとして依存しないでください。
耐久性のある選択肢は、モバイルSSHクライアント(永続接続とキー認証をサポートするものが複数あります)とtmuxの組み合わせ、またはネットワーク変更を乗り越えるmoshです。その上にブラウザターミナルツールを重ねることができます。ttydはウェブ経由でターミナルを公開します。vibetunnel(MITライセンス、Mac優先でクロスプラットフォームのLinux npm版あり)はターミナルをブラウザにプロキシし、Claude Codeエージェントの監視を目的として構築されており、Tailscale経由のリモートアクセスに対応しています。ブラウザターミナルを実行する場合は、必ずlocalhostにバインドしてTailscale経由でアクセスしてください。ウェブターミナルをパブリックに公開することは、形を変えた0.0.0.0の過ちと同じです。
Claude Code独自のネイティブリモートコントロールは軽量なユースケースをカバーします。アウトバウンドのみのHTTPS、スマートフォンからの操作、インバウンドポート不要。単一の稼働セッションを手軽に操作する最速の方法です。作業がどのターミナルよりも長く続く場合には、DIYスタックが頼りになります。
日常的なワークフロー
リモートボックスでの日常的な再デプロイループは3つのコマンドです。コードをプル、サービスを再起動、ログを確認。systemdで管理されたエージェントの場合は次のとおりです。
cd ~/app && git pull origin main
source venv/bin/activate && pip install -r requirements.txt
sudo systemctl restart my-agent
journalctl -u my-agent -f
git pullで最新コードを取得し、依存関係のインストールで新しい要件を反映させ、systemctl restartでサービスを再起動し、journalctl -u my-agent -fでサービスログをリアルタイムに確認して正常に起動したことを確かめます。journalctlはsystemdジャーナルを読み取るコマンドで、freedesktop.orgにドキュメントがあります。インタラクティブなtmuxエージェントの場合はさらにシンプルです。tmux attach -t myprojectでリアタッチし、git pullを実行して、エージェントの作業を続けます。
まとめ
ラッパーツールより長く使えるプリミティブを基盤にしましょう。ネットワークにはSSHとTailscale、操作するセッションにはtmux、無人で動作するサービスにはsystemd、そしてエージェントのポートをパブリックインターネットから遮断するセキュリティベースラインです。インタラクティブにエージェントを操作するのかサービスとしてホストするのかを明確にしてtmuxパターンとsystemdパターンを選択し、APIキーを扱う前にボックスを強化してから、ネイティブリモートコントロールやブラウザターミナルを便利な拡張として重ねてください。まずは新しいLinuxボックスと上記のTailscaleインストールコマンドから始めましょう。後はすべてそこから組み合わせていけます。
よくある質問
SSHから切断するとエージェントが終了してしまうのはなぜですか?
通常のSSHセッションはエージェントのプロセスをターミナルに紐付けるため、接続を閉じるとハングアップシグナルが送られてプロセスが終了します。代わりにtmuxセッション内でエージェントを実行してください。tmux new-session -s myprojectで開始し、エージェントを起動してから、Ctrl-bに続けてdでデタッチします。プロセスはサーバー上で動作し続け、後でtmux attach -t myprojectを使ってどのデバイスからでもリアタッチできます。
DIYのtmuxとSSHの構成の代わりにClaude Codeのネイティブリモートコントロールを使うべきはどんな場合ですか?
インフラを用意せずにスマートフォンやブラウザから単一の稼働セッションを操作するだけでよい場合は、ネイティブリモートコントロールを使用してください。アウトバウンドのみのHTTPSを使用し、インバウンドポートを開放しません。ただし、単一セッション限定であり、起動したターミナルが終了するとセッションも終了します。切断をまたいで継続する必要がある常時稼働、ヘッドレス、またはマルチプロジェクトの作業には、SSH、Tailscale、tmux、systemdを組み合わせたDIYスタックを構築してください。
moshはTailscaleネットワーク上で動作しますか?
はい、moshはTailscaleメッシュ上で動作します。必要なUDPポート範囲60000〜61000が認証済みデバイス間ですでに到達可能なため、ルーターの設定変更は不要です。唯一の失敗パターンは、tailscale up --sshでTailscale独自のSSHサーバーを有効にすることです。これはOpenSSHを置き換えてしまいます。moshはブートストラップのためにOpenSSH経由でmosh-serverを実行する必要があるため、Tailscaleと並行してOpenSSHをインストールして実行し続けてください。
systemdでシークレットを扱う際のEnvironmentFileとLoadCredentialの違いは何ですか?
EnvironmentFileは値を外部ファイルからロードすることでユニットファイルとsystemctl showの出力からシークレットを分離しますが、一度ロードされると値は稼働中のプロセス環境とD-Bus経由で読み取り可能な状態のままです。LoadCredentialはより強力で、プロセス環境ではなく制限されたディレクトリを通じてシークレットを渡すため、稼働中のプロセスの環境からアクセスできない状態を保ちます。設定値にはEnvironmentFileを、真のシークレットにはLoadCredentialを使用してください。