如何在 Headless VPS 安裝並執行 Gemini CLI
本指南教您在無介面 VPS 上部署 Gemini CLI,解決 Ubuntu 24.04 內建 Node 版本過低的問題。包含無需 sudo 的 npm 全域安裝、使用 API key 進行無瀏覽器驗證,以及利用 tmux 確保長時間 Agent 任務在 SSH 中斷後仍能持續運行。
專案目標
您將在自有伺服器上建立一個持續運行的 Gemini CLI。該工具可透過 SSH 連線,並能在您關閉筆記型電腦後,繼續執行長時間的 Agent 任務。安裝過程僅需三個指令。主要的挑戰在於處理所有針對桌面環境設計的功能:Google CLI 需要開啟瀏覽器進行登入,但您的伺服器並無瀏覽器。因此,本指南將著重於無介面 (headless) 的部署流程:包含安裝發行版預設未提供的最新版 Node,進行無需 root 權限的全域 npm install,使用不會留在 shell history 中的 API key 進行無瀏覽器驗證,並利用 tmux 確保 SSH 連線中斷時,執行中的任務不會停止。
Gemini CLI 是一個開源 (Apache-2.0) 的 Node 程式 (@google/gemini-cli),用於與 Google Gemini 模型通訊。它具備讀寫檔案、執行 shell 指令以及驅動工作目錄中工具的能力。在 VPS 上,它是一個小型且持續運行的 Agent;因此,執行該程式的使用者帳戶以及儲存在機器上的憑證,比本指南中的任何單一設定都更為重要。
前置作業與注意事項
- 一台全新的 Ubuntu 24.04 KVM VPS,並具備 root 或 sudo 權限。任何 KVM 方案皆可;CLI 本身非常輕量,閒置時僅佔用數百 MB RAM。
- Node.js 20 或更高版本。這是唯一的硬性版本限制,因為發行版套件的版本低於此要求 —— 請參閱下一節。
- 可連線至 Google APIs 的 Outbound HTTPS (port 443)。不需要開啟任何 Inbound ports;此工具為 Client 端而非 Server 端,因此無需在防火牆開啟任何孔洞。
- 無須在伺服器端使用瀏覽器的驗證方式:可使用來自 Google AI Studio 的 Gemini API key,或是建立回連至本地端瀏覽器的 SSH tunnel。若需執行腳本或自動化任務,建議使用 API-key 方式。
- Docker 或 Podman,僅在您需要
--sandbox隔離功能時才需要。此為選用項目,將於文末說明。
常見的陷阱:gemini 的首次執行登入流程是為桌面環境設計的。它會嘗試開啟瀏覽器,但在 Headless 環境下,該操作會失敗,或是提供一個無法運作的連結。請在開始前決定好驗證方式。
Node: 發行版套件版本過舊
Ubuntu 24.04 官方儲存庫內建的 Node 版本為 18.19.1,搭配 npm 9.2.0。Gemini CLI 的 package.json 要求使用 engines: { 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 將在不支援的 runtime 上執行。當程式呼叫預期存在於 Node 20+ 的 API 時,會發生異常或崩潰。此外,Node 18 已於 2025 年 4 月停止支援 (EOL),因此該版本已無維護價值。請在安裝 CLI 之前 先安裝目前的 LTS 版本。建議使用兩種方案之一:NodeSource(系統級簽章 apt 儲存庫)或 nvm(使用者級版本管理工具)。
若要讓主機上的所有使用者都能使用 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 --versionnode --version 必須輸出 v20.x 或更高版本 —— v24.x 為目前的 LTS 版本。請至 NodeSource 頁面確認最新的安裝指令碼;當有新的 LTS 版本發布時,請更新 URL 中的 setup_24.x。
若希望將 Node 限制在單一使用者的 home 目錄下,且不使用 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 擁有的檔案,造成數月後的問題。若對系統 Node 執行一般的 (無 sudo) 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 指向您的 home directory,讓 global 安裝的檔案存放於您擁有的目錄下:
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 是刻意為之:tmux(您將在兩個章節後於其中執行 CLI)會啟動一個 non-login shell,該 shell 會讀取 ~/.bashrc 並跳過 ~/.profile,因此若將 PATH 行寫在錯誤的檔案中,會導致 gemini 在關鍵位置失效。gemini --version 能正確印出版本號即代表測試成功。若出現 gemini: command not found,代表您的 PATH export 未生效,請參閱錯誤模式。若使用 nvm,請完全跳過 prefix 相關指令,因為 nvm 已將 globals 安裝在您的 home 目錄下。
若您先前執行過 sudo npm 且現在看到 Your cache folder contains root-owned files,請使用 sudo chown -R $(id -u):$(id -g) ~/.npm 進行修復。
無介面驗證問題及其解決方法
第一次互動式執行 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。即使您在筆電上開啟該 URL 並核准,Google 仍會將請求重導向至 http://localhost:PORT —— 這是「伺服器上的」localhost,筆電無法存取該連接埠。因此登入無法完成。
有兩種可靠的解決方案。
第一種是使用 API key,這是伺服器的標準做法。請在 Google AI Studio (aistudio.google.com) 建立金鑰,並將其作為環境變數傳遞給 CLI;系統會讀取 GEMINI_API_KEY 並完全跳過瀏覽器流程。接下來是「避免金鑰出現在歷史紀錄或公開檔案中」的注意事項。請勿直接在提示字元輸入 export GEMINI_API_KEY=AIza... —— 這會以明文形式儲存在 ~/.bash_history 中;也請勿將其存放在他人可讀取的檔案中。請將其寫入一個由 shell 在啟動時讀取的 mode-600 檔案:
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 ~/.bashrcchmod 600 代表僅限您的使用者可以讀取該檔案。請使用 printenv GEMINI_API_KEY 確認金鑰已成功載入環境變數;若無輸出,則 CLI 會退回瀏覽器流程並導致失敗。如果您偏好使用 ~/.gemini/ 中的 .env 檔案,規則相同,請設定 chmod 600 ~/.gemini/.env。
第二種方法是透過將 OAuth 回調 (callback) 隧道傳輸回您的筆電,來保留個人 Google 帳戶登入(以及其免費額度)。問題在於 CLI 的迴路 (loopback) 伺服器每次執行時會綁定一個隨機連接埠,除非您先使用 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;請在筆電瀏覽器中開啟並核准,當 Google 重導向至 http://localhost:8085/... 時,SSH 轉發會將請求傳送到 VPS 上的迴路伺服器,進而完成登入。若未固定連接埠,每次執行都會產生新的隨機連接埠,任何預先設定的 ssh -L 都無法捕捉。此方法雖然可行,但需要您在瀏覽器前操作,因此不適用於腳本。對於需要持續運行的任務,請使用 API key。
若使用 Vertex AI 或 Google Cloud 專案而非 AI Studio,請同時設定 GOOGLE_API_KEY 與 GOOGLE_GENAI_USE_VERTEXAI=true,或針對 Code Assist 授權設定 GOOGLE_CLOUD_PROJECT —— 應遵循相同的環境變數規範與 mode-600 檔案原則。
在 tmux 中執行,避免 SSH 連線中斷導致程序終止
直接從 SSH shell 啟動的 gemini 程序是該 shell 的子程序。若連線中斷(例如筆電關閉、Wi-Fi 斷開或閒置逾時),sshd 會關閉 pseudo-terminal,導致 shell 收到 SIGHUP,進而終止 CLI。若檔案編輯進行到 10 分鐘時程序就此結束,重新連線後將無法復原該程序。
tmux 可解決此問題,因為它是 shell 的父程序,而非由 sshd 擁有。這與 在遠端 VPS 的 tmux 中執行 AI coding agent 的模式相同,運作方式也完全一致:
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 的 session 則進行 attach,若不存在則建立。因此,這是每次登入後應執行的指令。tmux server 擁有內部的 shell,而非由你的 SSH session 擁有,因此連線中斷時 CLI 仍會持續運作。重新連線並 attach 後,即可回到原有的 scrollback 內容。
對於非互動式的腳本執行,Gemini CLI 提供 headless 模式:gemini -p "summarise the failing tests in this repo" 會印出答案並結束,而 --output-format json 則提供可供 pipe 至他處的 machine-readable output。在 tmux session 中執行長時間批次作業,或透過 cron 執行時,使用帶有 API key 的 headless 模式是最佳選擇。但需注意:cron job 不會讀取你的 login files,因此請在 crontab 行中提供專用的 GEMINI_API_KEY(或讓指令執行 source ~/.gemini_env),否則 CLI 會退回 browser flow 並導致失敗。
在執行正式環境的機器上進行沙盒化與權限管理
具備 shell 存取權限的 agent 即為一個 shell。Gemini CLI 可以執行指令,且預設會在執行高風險指令前進行詢問。然而,使用者常會使用 --yolo(自動核准所有工具呼叫),這會導致 agent 擁有該執行使用者的一切權限,進而能刪除檔案、推送 git 或存取內部服務。若該機器同時執行 production 環境,這將造成真實的影響範圍,而非僅是假設。
以下是三種控制措施,依其效益高低排序:
- 以專用的非特權使用者執行。 不要使用 root,也不要使用
sudo成員。建立一個擁有獨立 home 目錄的agent使用者,並於該目錄安裝 Node 與 CLI;如此一來,錯誤的指令將僅限於該帳號範圍內。這是價值最高的決策。 - 避免在該機器存放 production 憑證。 不要存放正式環境的
~/.aws/credentials,不要從 production 複製.env,也不要提供具備重要資源寫入權限的資料庫密碼。請提供 staging 或唯讀的憑證。 - 使用內建的沙盒。 若已安裝 Docker 或 Podman,
gemini --sandbox(或GEMINI_SANDBOX=docker) 會在與主機檔案系統及網路隔離的 container 中執行 agent 的工具呼叫。這並非非特權使用者的替代方案,但在同一台 VPS 執行實際工作時,這是強大的第二層防禦。
若您在執行 Gemini CLI 的同時也執行其他自架工具(例如 在同一台 VPS 上向 agent 提供工具的 MCP server),請將每個新增的功能視為 agent 可觸及的擴大攻擊面,並將分配給它的 token 範圍限制在單一任務中。
配額、費用與認證路徑選擇
認證路徑決定計費方式。使用個人 Google 帳戶(OAuth 路徑)會使用免費的 Gemini Code Assist 層級,並設有每分鐘與每日的實際限制;若超過限制,請求將回傳 rate-limit 錯誤,直到時間窗口重置。來自 AI Studio 的 API key 依專案而定,可能是免費層級或計費層級;計費金鑰會提高限制並按 token 計費。Vertex 與 Cloud-project 認證則透過 Google Cloud 計費。
兩點實務建議。處於迴圈中的自動化代理程式會快速消耗配額,因此在將其交給 cron job 執行前,請先觀察前幾次運作狀況。此外,若您選擇伺服器端模型是為了隱私或非計量推論,而非使用 Google 託管的模型,則需使用不同的工具 —— 在 VPS 上使用 Ollama 自行託管 open LLM可將權重與提示詞保留在您自己的裝置上,代價是模型規模會比 Gemini 小得多。
保持更新
Gemini CLI 的發佈頻率很高。由於您將其安裝在使用者權限的 prefix 中,因此更新時不需要使用 sudo:
npm install -g @google/gemini-cli@latest
gemini --version目前提供不同的發佈管道:@latest 為穩定版,@preview 為每週預覽版,@nightly 為開發版 —— 若要確保穩定,請將版本固定在 @latest。在使用 nvm 時,全域套件會安裝在目前的 Node 版本下,因此在執行 nvm use 切換 Node 版本後,可能需要重新安裝 CLI。建議直接閱讀 release notes,而非追逐每一次的 patch。
Failure modes, with the exact strings
npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' },接著 CLI 在執行時崩潰。 Node 版本過舊 —— 發行版提供的版本為 18.19.1,且已超出生命週期 (end-of-life)。請從 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/bin 放入 PATH,並以一般使用者身分重新安裝。若先前的 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 callback 指向伺服器而非您的筆記型電腦。請使用 API-key 路徑 (GEMINI_API_KEY),或固定 OAUTH_CALLBACK_PORT,透過 ssh -L 進行 SSH 轉發,並在本地端開啟該 URL。
SSH 中斷時程序消失。 您直接在 SSH shell 中執行 gemini,因此該程序為該 shell 的子程序,並隨 pty 在斷開連線時結束。無法復原。請在每個 session 開始時執行 tmux new -A -s gemini,並在其中執行 CLI。
已設定 key 但驗證仍失敗 —— CLI 回到驗證選項,或請求回傳 HTTP 400 的 API key not valid。 Key 不在 CLI 偵測到的環境變數中。請使用 printenv GEMINI_API_KEY 確認;若結果為空,代表您的 ~/.gemini_env 未被載入 —— 請檢查該行是否位於 ~/.bashrc 中,互動式 shell (包含 tmux) 會讀取此檔案,但 cron 與其他非互動式 shell 則不會。Key 值內包含多餘的空格或引號也會導致 API key not valid。
429 / RESOURCE_EXHAUSTED / 達到速率限制 (rate-limit) 訊息。 您已達到該驗證層級的配額。請等待週期重置、降低 agent 速度,或改用付費 API key。若 agent 卡在重試迴圈中會持續觸發此錯誤 —— 請停止該程序並檢查其行為。
FAQ
如何在 headless server 上進行 Gemini CLI 驗證?
請使用 API key 而非瀏覽器登入。在 Google AI Studio 建立 key,並將其放入 shell 會讀取的 mode-600 檔案 (export GEMINI_API_KEY=...),如此 CLI 就會完全跳過 OAuth 瀏覽器流程。若您必須使用個人帳戶的免費層級,請使用 OAUTH_CALLBACK_PORT=8085 固定 loopback port,並透過 ssh -L 8085:localhost:8085 user@server 將其轉發回您的筆電,接著在本地端開啟顯示的 URL。但此方法需要您在瀏覽器前操作,因此不適用於腳本。
為什麼 npm global install 需要 sudo,該如何避免?
因為 npm 的預設 global prefix 為 /usr/lib/node_modules,您的使用者權限無法寫入,導致直接執行 npm install -g 時會出現 EACCES 錯誤。錯誤的解法是使用 sudo npm -g,這會留下 root 權限的檔案,導致後續安裝失敗。正確的解法是將 prefix 指向您的 home 目錄 (npm config set prefix ~/.npm-global),並將其 bin 加入 PATH,或是使用 nvm,它會自動將 global packages 安裝在您的 home 目錄下。
如何在斷開連線後保持 Gemini CLI 持續執行?
請在 tmux 中執行。從 SSH shell 啟動的程序會在連線中斷時停止,因為它是該 shell 的子程序;tmux 則是在一個分離的 server 下執行 shell,該 server 在連線中斷後仍會繼續運作。請使用 tmux new -A -s gemini,在其中執行 gemini,使用 Ctrl-b d 進行分離 (detach),稍後再透過 tmux attach -t gemini 重新連接 (reattach)。
在 production 環境執行 Gemini CLI 是否安全?
必須謹慎操作,因為擁有 shell 存取權限的 agent 可以執行該使用者所擁有的所有權限。請以專用的非特權使用者身份執行且不給予 sudo 權限、不要將 production 憑證存放在該機器上、避免使用 --yolo 自動核准,並使用 --sandbox (Docker 或 Podman) 來隔離工具呼叫與 host 系統。執行該程序的帳戶權限比您設定的任何單一 flag 都更重要。
Gemini CLI 需要開啟任何防火牆 port 嗎?
不需要。它是一個向 Google APIs 發出 outbound HTTPS 呼叫的 client,因此只需要 outbound port 443,不需要任何 inbound ports。如果您使用 OAuth tunnel,被固定的 callback port (例如 8085) 是位於 localhost,並透過您的 SSH forward 進行存取,而非透過開啟的 inbound port。請保持 inbound 埠號處於封鎖狀態。