SSD Nodes Learn
ガイド Matt Connor著者 Matt Connor ・更新日 2026-07-24

ヘッドレスVPSでGemini CLIを動かす方法

ブラウザのないVPSでGemini CLIを動かす手順を解説します。最新のNode.jsの導入から、sudo不要のnpm install、API keyによるブラウザレス認証、tmuxを用いたSSH切断対策まで詳しく説明します。デスクトップ環境がない環境での認証エラーを回避し、軽量なAIエージェントを構築できます。

作成するもの

所有しているサーバー上で動作する、常時稼働の Gemini CLI です。SSH 経由でアクセスでき、ノートPCを閉じてもエージェントのタスクが継続されます。インストールは3つのコマンドで完了します。主な課題は、デスクトップ環境を前提とした設定です。Google の CLI はログインにブラウザを必要としますが、サーバーにはブラウザがありません。そのため、本ガイドではヘッドレス環境での構築に焦点を当てます。具体的には、ディストリビューション標準ではない最新の Node、root権限を必要としない global な npm install、シェル履歴に残らない API key を使用したブラウザレス認証、そして SSH セッションが切断されてもタスクを継続させるための tmux を使用します。

Gemini CLI は、Google の Gemini モデルと通信するオープンソース (Apache-2.0) の Node プログラム (@google/gemini-cli) です。ファイルの読み書き、shell コマンドの実行、作業ディレクトリ内のツールの操作が可能です。VPS 上では、常に稼働可能な軽量なエージェントとして機能します。そのため、実行ユーザーの権限とサーバー内に保存される認証情報の設定が、他の設定よりも重要になります。

前提条件と注意点

  • root または sudo 権限を持つ、新規インストール済みの Ubuntu 24.04 KVM VPS。KVM プランはどれでも動作します。CLI 自体は軽量で、アイドル時のメモリ使用量は数百 MB 程度です。
  • Node.js 20 以降。これより古いバージョンでは動作しません。ディストリビューションのパッケージはこれより古いため、注意してください。
  • Google API へのアウトバウンド HTTPS (port 443) 通信。インバウンドポートの開放は不要です。クライアントとして動作するため、ファイアウォールの設定変更は必要ありません。
  • サーバー上でブラウザを使用せずに認証する方法。Google AI Studio の Gemini API key を使用するか、ローカルマシンのブラウザへ SSH tunnel を張るかのいずれかです。スクリプトや自動実行を行う場合は、API key の使用を推奨します。
  • Docker または Podman。--sandbox による分離機能を利用する場合のみ必要です。オプションであり、後半で説明します。

注意点:gemini の初回ログインフローは、デスクトップ環境向けに設計されています。ブラウザを起動しようとするため、ヘッドレス環境では失敗するか、機能しないリンクが表示されます。作業を開始する前に、認証方法を決定しておいてください。

Node: ディストリビューションのパッケージが古すぎます

Ubuntu 24.04 の標準リポジトリには Node 18.19.1 と npm 9.2.0 が含まれています。Gemini CLI の package.jsonengines: { node: ">=20" } を要求しますが、npm はデフォルトではバージョンの不一致を停止しません。そのままインストールが進み、差異を示す警告が表示されます。

npm WARN EBADENGINE Unsupported engine {
npm WARN EBADENGINE   package: '@google/gemini-cli@0.50.0',
npm WARN EBADENGINE   required: { node: '>=20' },
npm WARN EBADENGINE   current: { node: 'v18.19.1', npm: '9.2.0' }
npm WARN EBADENGINE }

警告を無視して実行すると、サポートされていないランタイムで CLI が動作します。Node 20 以降の API を呼び出した瞬間に、動作不良やクラッシュが発生します。また、Node 18 は 2025 年 4 月にサポート終了(EOL)を迎えたため、どちらにせよ解決策にはなりません。CLI をインストールする に、最新の LTS をインストールしてください。推奨される方法は、NodeSource(システム全体で使用可能な署名付き apt リポジトリ)または nvm(ユーザーごとのバージョンマネージャー)の 2 つです。一方を選択してください。

サーバー上の全ユーザーで Node を使用したい場合は、NodeSource を使用します。

sudo apt-get update
sudo apt-get install -y ca-certificates curl gnupg
curl -fsSL https://deb.nodesource.com/setup_24.x | sudo -E bash -
sudo apt-get install -y nodejs
node --version

node --versionv20.x 以上である必要があります。v24.x が現在の有効な LTS です。最新のセットアップスクリプトについては NodeSource のページを確認してください。新しい LTS がリリースされた場合は、URL 内の setup_24.x を更新してください。

特定のユーザーのホームディレクトリ内のみに Node を保持し、sudo を使用したくない場合は、nvm を使用します。

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
source ~/.bashrc
nvm install --lts
node --version

URL 内の v0.40.1 は執筆時点のバージョンです。最新のリリースについては nvm の README を確認し、実行前にバージョンを書き換えてください。nvm には大きな利点があります。Node とグローバルパッケージを ~/.nvm にインストールするため、次節で説明するグローバルインストールの権限問題が発生しません。nvm を使用する場合、npm-prefix の設定手順は不要です。

sudo npm -gを使用せずにCLIをインストールする

sudo npm install -g @google/gemini-cliというコマンドは魅力的ですが、実行しないでください。root権限のglobal prefixを使用すると、その後のすべてのインストールで権限エラーが発生します。また、npm cache内にroot所有のファイルが残り、数ヶ月後に問題を引き起こします。sudoを使わずにシステム版のNodeに対してnpm install -gを実行すると、別のエラーが発生します。

npm error code EACCES
npm error syscall mkdir
npm error path /usr/lib/node_modules/@google
npm error errno -13
npm error Error: EACCES: permission denied, mkdir '/usr/lib/node_modules/@google'

これは、npmが/usr/libに書き込もうとして失敗している状態です。解決策はsudoを使うことではありません。npmのglobal prefixをホームディレクトリに設定し、global installの先をユーザーが所有する場所にすることです。

mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
npm install -g @google/gemini-cli
gemini --version

~/.bashrcではなく~/.profileとするのは意図的です。2セクション後にCLIを実行するtmuxは、~/.bashrcを読み込み~/.profileをスキップするnon-login shellを開始します。そのため、誤ったファイルにPATHを記述すると、必要な場所でgeminiが認識されなくなります。gemini --versionでバージョン番号が表示されればテスト成功です。もしgemini: command not foundが表示される場合は、PATHのexportが反映されていません。失敗パターンを確認してください。nvmを使用している場合は、prefixに関する行はすべてスキップしてください。nvmはすでにホームディレクトリ以下にglobalsをインストールします。

以前にsudo npmを実行しており、現在Your cache folder contains root-owned filesが表示される場合は、sudo chown -R $(id -u):$(id -g) ~/.npmで一度修復してください。

Headless環境での認証問題と解決策

初回に gemini を対話モードで実行すると、Googleアカウントでのログインが求められます。デスクトップ環境ではブラウザのタブが開きます。しかし、Headless VPSにはブラウザがないため、localhostのURLが表示されるか、あるいは次のようなエラーが発生します。

Failed to open browser. Please visit the following URL to authorize:
https://accounts.google.com/o/oauth2/v2/auth?...&redirect_uri=http://localhost:PORT

原因は redirect_uri=http://localhost:PORT です。ノートPCでそのURLを開いて承認しても、Googleは http://localhost:PORT にリダイレクトします。これはサーバー上のlocalhostであり、ノートPCからはアクセスできません。そのため、ログインが完了しません。

解決策は2つあります。

1つ目はAPI keyを使用する方法です。サーバー環境ではこれが推奨されます。Google AI Studio (aistudio.google.com) でkeyを作成し、環境変数としてCLIに渡してください。CLIは GEMINI_API_KEY を読み取るため、ブラウザによる認証プロセスを完全にスキップできます。ここで注意すべきは、履歴や誰でも読み取れるファイルに情報を残さないことです。プロンプトに直接 export GEMINI_API_KEY=AIza... を入力しないでください。~/.bash_history に平文で保存されてしまいます。また、他のユーザーが読み取れるファイルにも保存しないでください。起動時にshellが読み込む、権限を制限したファイルに書き込んでください。

umask 077
printf 'export GEMINI_API_KEY=%s\n' 'AIzaSyYOUR_KEY_HERE' > ~/.gemini_env
chmod 600 ~/.gemini_env
echo '[ -f ~/.gemini_env ] && . ~/.gemini_env' >> ~/.bashrc
source ~/.bashrc

chmod 600 を設定することで、そのファイルはユーザー自身のみが読み取れるようになります。printenv GEMINI_API_KEY を実行して、keyが正しく環境変数に読み込まれているか確認してください。何も表示されない場合は、CLIはブラウザ認証を試行し、失敗します。また、~/.gemini/ にある .env ファイルを使用することも可能です。その場合も、chmod 600 ~/.gemini/.env のように権限を制限してください。

2つ目の方法は、OAuthのコールバックをノートPCへトンネリングすることで、個人のGoogleアカウント(および無料枠)を維持する方法です。注意点として、CLIのループバックサーバーは実行ごとに「ランダムな」ポートを使用します。そのため、OAUTH_CALLBACK_PORT 環境変数でポートを固定してから、そのポートを転送する必要があります。

# from your laptop, forward the callback port into the SSH session:
ssh -L 8085:localhost:8085 user@your-server
# then, on the server, pin the callback to the same port and start the CLI:
export OAUTH_CALLBACK_PORT=8085
gemini

CLIはブラウザを開けないため、認証URLが表示されます。それをノートPCのブラウザで開き、承認してください。Googleが http://localhost:8085/... にリダイレクトすると、SSHトンネルを通じてVPS上のループバックサーバーにリダイレクトされ、ログインが完了します。ポートを固定しない場合、実行のたびに新しいランダムなポートが割り当てられるため、事前に ssh -L を設定していてもキャッチできません。この方法は動作しますが、ブラウザでの操作が必要なため、スクリプトには適していません。常時実行するプロセスには、API keyを使用してください。

AI Studioの代わりにVertex AIまたはGoogle Cloudプロジェクトを使用する場合は、GOOGLE_API_KEYGOOGLE_GENAI_USE_VERTEXAI=true、あるいは Code Assist ライセンスの場合は GOOGLE_CLOUD_PROJECT を設定してください。API keyと同様に、環境変数を使用し、mode-600のファイルで管理してください。

SSHセッションが切断されてもプロセスが終了しないよう、tmux内で実行してください

SSHシェルから直接起動したgeminiプロセスは、そのシェルの子プロセスになります。ノートPCの閉鎖、Wi-Fiの切断、アイドルタイムアウトなどで接続が失われると、sshdが疑似端末を破棄します。その結果、シェルがSIGHUPを受け取り、CLIも終了します。ファイル編集を開始して10分後に実行中のタスクも、接続と共に停止し、再接続してもプロセスを復旧させることはできません。

tmuxを使用すると、sshdの代わりにtmuxがシェルを管理するため、この問題が解決します。これは リモートVPS上のtmux内でAIコーディングエージェントを実行する 場合と同じパターンであり、ここでも同様に機能します。

sudo apt install -y tmux
tmux new -A -s gemini
# inside the session:
gemini
# detach with Ctrl-b then d — the task keeps running
# reconnect later from any machine:
tmux attach -t gemini

tmux new -A -s geminiは、geminiという名前のセッションが存在すればアタッチし、存在しなければ新規作成します。そのため、ログイン直後に実行すべきコマンドはこれだけです。tmux内のシェルは、SSHセッションではなく、デタッチされたtmuxサーバーに属します。したがって、接続が切れてもCLIは動作し続けます。再接続してアタッチすれば、元のスクロールバック状態に戻れます。

対話なしのスクリプト実行には、Gemini CLIのヘッドレスモードがあります。gemini -p "summarise the failing tests in this repo"は回答を出力して終了し、--output-format jsonは他のプロセスへ渡すためのマシン読み取り可能な出力を提供します。APIキーを使用したヘッドレスモードは、tmuxセッションで長時間実行するバッチジョブや、cronからの実行に最適です。ただし、注意点があります。cronジョブはログインファイルを読み込まないため、crontabの行に独自の GEMINI_API_KEY を指定するか、コマンド内で ~/.gemini_env を読み込ませる必要があります。そうしないと、CLIはブラウザ経由のフローにフォールバックし、エラーになります。

本番環境が稼働しているマシンでのサンドボックス化と権限管理

シェルアクセスを持つエージェントは、実質的にシェルとして機能します。Gemini CLIはコマンドを実行できます。デフォルトでは、リスクのあるコマンドを実行する前に確認を求めますが、--yolo(すべてのツール呼び出しを自動承認する設定)が使用されると、実行ユーザーの権限でファイルの削除、gitへのpush、内部サービスへのアクセスが可能になります。本番環境が稼働しているマシンでは、これは仮説ではなく、現実的な被害範囲(blast radius)となります。

効果の高い順に、3つの制御策を挙げます。

  • 専用の非特権ユーザーとして実行する。 rootやsudoのメンバーとして実行しないでください。独自のホームディレクトリを持つagentユーザーを作成し、そこにNodeとCLIをインストールしてください。これにより、誤った指示による影響をそのアカウント内に限定できます。これが最も重要な決定事項です。
  • 本番環境の認証情報をマシンに置かない。 本番用の~/.aws/credentialsや、本番環境からコピーした.envを置かないでください。重要なリソースへの書き込み権限を持つデータベースパスワードも避けてください。ステージング環境用、または読み取り専用の認証情報を付与してください。
  • 組み込みのサンドボックスを使用する。 DockerまたはPodmanがインストールされていれば、gemini --sandbox(またはGEMINI_SANDBOX=docker)は、ホストのファイルシステムやネットワークから隔離されたコンテナ内でエージェントのツール呼び出しを実行します。これは非特権ユーザーの代わりになるものではありませんが、同じVPSで実業務を行っている場合の強力な第2層の防御となります。

Gemini CLIを他のセルフホストツール(例えば、同じVPS上でエージェントにツールを公開するMCP serverなど)と併用する場合は、機能が追加されるたびにエージェントの到達範囲(surface)が広がると考えてください。エージェントに渡すトークンの権限は、単一のジョブに厳密に限定してください。

Quota、コスト、および選択した auth path について

auth path によって課金方法が決まります。個人の Google アカウント(OAuth path)を使用する場合、Gemini Code Assist の free tier が適用されます。これには分単位および日単位の制限があり、制限を超えると、ウィンドウがリセットされるまで rate-limit error が返されます。AI Studio の API key は、プロジェクトに応じて free tier または課金対象になります。課金対象の key は制限が緩和されますが、token ごとに料金が発生します。Vertex および Cloud-project auth の課金は Google Cloud を通じて行われます。

2つの実用的な注意点があります。ループ内で動作する unattended agent は、quota を急速に消費する可能性があります。cron job に設定して信頼する前に、最初の数回は動作を確認してください。また、Google のホスト型モデルではなく、プライバシーや unmetered inference を目的としてサーバーサイドのモデルを使用する場合は、別のツールが必要です。VPS 上の Ollama で open LLM を self-hosting する方法であれば、Gemini よりもはるかに小さなモデルを実行することになりますが、weights と prompts を自身のマシン内に保持できます。

アップデートの維持

Gemini CLI は頻繁にリリースされます。ユーザー所有の prefix にインストールされているため、アップデートに sudo は不要です。

npm install -g @google/gemini-cli@latest
gemini --version

リリースチャネルがあります。@latest は stable、@preview は weekly preview、@nightly は bleeding edge です。信頼性が重要な環境では @latest に固定してください。nvm を使用している場合、global package はアクティブな Node バージョンの配下にあります。Node を nvm use で切り替えた後は、CLI の再インストールが必要になる場合があります。すべてのパッチを追うのではなく、リリースノートを確認してください。

失敗パターンと正確なエラー文字列

npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' }、および実行時のCLIクラッシュ。 Nodeのバージョンが古すぎます。ディストリビューションの18.19.1は、すでにサポート終了(EOL)を迎えています。NodeSourceまたはnvmからNode 20以降をインストールしてください。インストール後はnode --versionで確認してください。複数のNodeがインストールされている場合は、which node/usr/bin/nodeではなく、新しいバージョンを指しているか確認してください。

npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...' root権限のprefixへのグローバルインストールが原因です。sudoを使用しないでください。npm config set prefix ~/.npm-globalを設定し、~/.npm-global/binPATHに配置して、通常のユーザーとして再インストールしてください。以前のsudo npmによってroot所有のキャッシュファイル(Your cache folder contains root-owned files)が残っている場合は、sudo chown -R $(id -u):$(id -g) ~/.npmを実行してください。

Failed to open browser、ログインのハングアップ、またはredirect_uri=http://localhost:PORTへの接続不可。 OAuthフローがサーバー上に存在しないブラウザを必要としています。また、localhostへのコールバックがノートPCではなくサーバーを指しています。API-key(GEMINI_API_KEY)を使用するか、OAUTH_CALLBACK_PORTを固定してください。その後、ssh -LでSSH経由で転送し、ローカルでURLを開いてください。

SSH切断時にプロセスが消失。 SSHシェルから直接geminiを実行したため、プロセスがシェルの子プロセスとなり、切断時にptyと共に終了しました。復旧はできません。セッションの開始時に必ずtmux new -A -s geminiを使用し、その中でCLIを実行してください。

キーを設定しても認証に失敗する — CLIが認証選択に戻る、またはリクエストがHTTP 400API key not validを返す。 キーがCLIから参照可能な環境変数に含まれていません。printenv GEMINI_API_KEYで確認してください。空である場合は、~/.gemini_envが読み込まれていません。~/.bashrcに該当する行があるか確認してください。tmuxを含むインタラクティブなシェルはこれを読み込みますが、cronなどの非インタラクティブなシェルは読み込みません。キーの値に不要なスペースや引用符が含まれている場合も、API key not validが発生します。

429 / RESOURCE_EXHAUSTED / レート制限メッセージ。 使用している認証プランのクォータに達しました。リセットされるまで待機するか、エージェントの動作速度を落とすか、有料のAPIキーに移行してください。リトライを繰り返しているエージェントは、このエラーを出し続けます。エージェントを停止し、動作内容を確認してください。

FAQ

ヘッドレスサーバーで Gemini CLI を認証する方法は?

ブラウザログインではなく、API key を使用してください。Google AI Studio で key を作成し、シェルが読み込む mode-600 のファイル (export GEMINI_API_KEY=...) に保存します。これにより、CLI は OAuth のブラウザフローを完全にスキップします。個人の無料枠を使用したい場合は、OAUTH_CALLBACK_PORT=8085 で loopback port を固定し、ssh -L 8085:localhost:8085 user@server でノートPCへ転送して、ローカルで表示された URL を開いてください。ただし、ブラウザでの操作が必要なため、スクリプトには適していません。

なぜ npm の global install で sudo が必要になり、どうすれば回避できますか?

npm のデフォルトの global prefix が /usr/lib/node_modules であり、ユーザーに書き込み権限がないため、通常の npm install -gEACCES で失敗します。sudo npm -g は誤った解決策です。root 所有のファイルが残り、後のインストールを妨げます。正しい解決策は、prefix をホームディレクトリ (npm config set prefix ~/.npm-global) に設定し、その binPATH に追加することです。または、global package を自動的にホームディレクトリにインストールする nvm を使用してください。

切断後も Gemini CLI を実行し続けるにはどうすればよいですか?

tmux 内で実行してください。SSH シェルから開始されたプロセスは、そのシェルの子プロセスであるため、接続が切れると終了します。tmux は、切断後も生存するデタッチされたサーバー上でシェルを実行します。tmux new -A -s gemini を使用し、中で gemini を実行し、Ctrl-b d でデタッチし、後で tmux attach -t gemini でアタッチしてください。

本番環境のサーバーで Gemini CLI を実行しても安全ですか?

慎重に行う必要があります。シェルアクセス権を持つエージェントは、実行ユーザーができることすべてを実行できるからです。sudo 権限のない専用の非特権ユーザーとして実行し、本番環境の認証情報をマシンに置かないようにしてください。--yolo の自動承認は避け、--sandbox (Docker または Podman) を使用してツール呼び出しをホストから隔離してください。設定するフラグよりも、実行するアカウントの権限が重要です。

Gemini CLI のためにファイアウォールのポートを開ける必要はありますか?

不要です。Gemini CLI は Google の API に対してアウトバウンドの HTTPS コールを行うクライアントであるため、アウトバウンドの port 443 は必要ですが、インバウンドのポートは不要です。OAuth tunnel を使用する場合、固定された callback port (例: 8085) は localhost 上に存在し、SSH 転送を通じてアクセスされます。インバウンドポートは閉じたままにしてください。

#gemini-cli#node#tmux#headless#ai#vps