如何在无头 VPS 上部署运行 Gemini CLI
在无头 VPS 上运行 Gemini CLI 的完整指南。涵盖 Node.js 24 环境配置、无需 sudo 的 npm 安装、通过 API Key 实现无浏览器身份验证,以及使用 tmux 确保 SSH 断开后任务持续运行的技巧。
构建内容
在您拥有的服务器上运行始终在线的 Gemini CLI。通过 SSH 访问它,并运行长时间的代理任务。即使关闭笔记本电脑,任务也会继续运行。安装只需执行 3 条命令。真正需要处理的是所有依赖桌面环境的部分:Google 的 CLI 希望打开浏览器完成登录,但服务器没有浏览器。因此,本指南的大部分内容都介绍无头运行方式、发行版不会提供的当前 Node、无需 root 的全局 npm 安装、不会将 API 密钥写入 shell 历史记录的无浏览器身份验证,以及 tmux。这样,即使 SSH 会话断开,正在运行的任务也不会随之终止。
Gemini CLI 是一个开源的(Apache-2.0)Node 程序(@google/gemini-cli)。它与 Google 的 Gemini 模型通信,可以读取和写入文件、运行 shell 命令,并驱动工作目录中的工具。在 VPS 上,它是一个小型、始终可用的代理。您可以让它持续工作。因此,它运行所使用的账户以及保存在服务器上的凭据,比本指南中的任何单项设置都更重要。
前置条件和需要注意的问题
- 一台全新的 Ubuntu 24.04 KVM VPS,具有 root 或 sudo 权限。任何 KVM 套餐都可以;该 CLI 本身资源占用很低,空闲时只需几百 MB RAM。
- Node.js 20 或更高版本。这是唯一严格的最低版本要求,而发行版软件包低于此版本,详见下一节。Node 20 已于 April 30, 2026 结束生命周期,因此请安装 24。
- 可通过 HTTPS(端口 443)访问 Google API 的出站网络连接。不需要任何入站端口;这是客户端而不是服务器,因此无需为此开放防火墙端口。
- 一种不需要在服务器上使用浏览器的身份验证方式:使用 Google AI Studio 提供的付费 Gemini API key,或使用 Google 登录。对于无头服务器,Google 登录会要求您将代码粘贴回终端。API key 方式适用于脚本和无人值守运行。
- 仅当您需要
--sandbox隔离时才需要 Docker 或 Podman。此项为可选配置,本文末尾附近会介绍。
现在最容易引发问题的是账号,而不是浏览器。Google 于 May 19, 2026 宣布,自 June 18, 2026 起,Gemini CLI 将不再为 Google AI Pro 和 Ultra 订阅者,以及免费使用该服务的用户提供请求处理,并会将这些用户引导至其替代产品 Antigravity CLI(agy)。Gemini CLI 仍支持付费 Gemini API key、Gemini Enterprise Agent Platform API key,以及组织持有的 Gemini Code Assist Standard 或 Enterprise 许可证。开始前请先确定身份验证方式。
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 会在不受支持的运行时上运行。一旦调用预期存在的 Node 20+ API,就可能出现异常或崩溃。Node 18 也已于 2025 年 4 月结束生命周期,因此无论如何都无法继续使用。请在安装 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 或更高版本,才能满足 CLI 的要求。但 Node 20 自 2026 年 4 月 30 日起已结束生命周期,因此应选择 v24.x,即当前的活跃 LTS 版本。Node 26 计划于 2026 年 10 月 28 日成为活跃 LTS 版本。请查看 NodeSource 页面获取当前的安装脚本;URL 中的 setup_24.x 是新 LTS 版本发布后需要更新的部分。
如果希望将 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 步骤。
安装 CLI,但不使用 sudo npm -g
看似合理的命令是 sudo npm install -g @google/gemini-cli。不要这样做。由 root 拥有的全局 prefix 会导致之后每次安装都出现权限错误,并在 npm 缓存中留下由 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 的全局 prefix 指向主目录,使全局安装写入当前用户拥有的位置:
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。tmux 启动的是非登录 shell,该 shell 会读取 ~/.bashrc,但跳过 ~/.profile。因此,如果将 PATH 行写入错误的文件,gemini 就会在您实际需要的位置不可用。gemini --version 能够输出版本号,就说明配置正确。若输出 gemini: command not found,说明您的 PATH 导出未生效,请参阅故障模式。使用 nvm 时,完全跳过这些 prefix 行:nvm 已经将全局安装放在您的主目录下。
如果您之前执行过 sudo npm,现在看到 Your cache folder contains root-owned files,请使用 sudo chown -R $(id -u):$(id -g) ~/.npm 修复一次。
无头环境下的身份验证问题及解决方法
首次以交互方式运行 gemini 时,它会提供使用 Google 账户登录的选项。在桌面系统上,这会打开浏览器标签页。在无头 Linux VPS 上,CLI 会先检查显示环境。如果 DISPLAY、WAYLAND_DISPLAY 和 MIR_SOCKET 都未设置,它完全不会尝试启动浏览器,而是打印登录链接,并等待您将代码粘贴回来:
Please visit the following URL to authorize the application:
https://accounts.google.com/o/oauth2/v2/auth?...
Enter the authorization code:这种流程可以通过普通 SSH 使用,但每次都需要您打开浏览器。而且从 June 18, 2026 起,只有当您的 Google 账户仍在 Gemini CLI 支持范围内时,才能通过此流程登录。
有两种可行方法。
第一种是使用 API key,这也是服务器上的默认选择。在已启用结算的项目中,通过 Google AI Studio(aistudio.google.com)创建密钥。由于 Gemini CLI 不再提供免费使用,这一步是必需的。然后将密钥作为环境变量传递给 CLI;CLI 会读取 GEMINI_API_KEY,并完全跳过浏览器流程。接下来需要避免密钥进入历史记录和其他用户可读的文件。不要在提示符中输入 export GEMINI_API_KEY=AIza...,因为它会以明文写入 ~/.bash_history;也不要将密钥放入其他用户可读的文件。将它写入一个权限为 600 的文件,并让 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 ~/.bashrcchmod 600 表示只有您的用户可以读取该文件。使用 printenv GEMINI_API_KEY 确认密钥已进入环境。如果没有任何输出,CLI 会退回身份验证选择器,而不是使用该密钥。如果您更喜欢这种布局,CLI 也会读取 ~/.gemini/ 中的 .env 文件。安全规则相同,因此 chmod 600 ~/.gemini/.env。
第二种方法是直接使用 Google 登录。此方法在无头服务器上不需要隧道或开放端口。从 June 18, 2026 起,它主要适用于组织提供的 Gemini Code Assist Standard 或 Enterprise 许可证(同时设置 GOOGLE_CLOUD_PROJECT);不再支持免费个人账户以及 Google AI Pro 或 Ultra 订阅。通过普通 SSH 会话启动 CLI,并选择使用 Google 登录:
gemini将打印出的 URL 复制到笔记本电脑上的浏览器中并批准。Google 会重定向到 https://codeassist.google.com/authcode,该页面会显示授权代码。将代码粘贴到 VPS 上的 Enter the authorization code: 提示符中,登录即完成。服务器不会等待回调,因此无需固定端口,也无需配置 ssh -L。只有当 CLI 检测到显示环境时,OAUTH_CALLBACK_PORT 才会影响它使用的环回流程。如果您通过 X11 转发(ssh -X)连接,系统会设置 DISPLAY,CLI 也会改用该环回流程,并重定向到服务器上的 http://127.0.0.1:PORT/oauth2callback;运行 NO_BROWSER=true gemini 可强制使用粘贴代码流程。该方法可以使用,但需要您一直在浏览器旁,因此不适合脚本。对于需要长期运行的任务,请使用 API key。
如果使用 Vertex AI 或 Google Cloud 项目,而不是 AI Studio,请同时设置 GOOGLE_API_KEY 和 GOOGLE_GENAI_USE_VERTEXAI=true;如果使用 Code Assist 许可证,则设置 GOOGLE_CLOUD_PROJECT。环境变量管理规则相同,也应使用权限为 600 的文件。
在 tmux 中运行,避免 SSH 连接断开导致进程终止
直接从 SSH shell 启动的 gemini 进程属于该 shell 的子进程。连接断开、笔记本关闭、Wi-Fi 中断或空闲超时都会导致 sshd 拆除伪终端,shell 收到 SIGHUP 后又会向 CLI 发送挂断信号。正在编辑文件的任务即使已运行 10 分钟,也会随之终止;重新连接后没有可恢复的进程。
tmux 通过接管 shell 解决此问题,而不是让 sshd 接管 shell。这与在远程 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如果名为 gemini 的会话存在,tmux new -A -s gemini 会连接到该会话;如果不存在,则创建该会话。因此,每次登录后都应立即运行这条命令。会话中的 shell 属于已分离的 tmux 服务器,而不是当前 SSH 会话,因此连接断开后 CLI 仍会继续运行。重新连接并附加会话后,您可以回到同一份滚动缓冲区。如果您在同一台服务器上运行多个代理会话,应为每个会话使用一个 tmux 会话。与 Claude Code 不同,这些会话在这里无法相互通信;Claude Code 可以让同一 VPS 上的一个会话将文本传递给另一个会话。因此,请让每个 Gemini 任务独立运行,或通过磁盘上的文件进行协调。
对于非交互式脚本运行,Gemini CLI 提供无头模式:gemini -p "summarise the failing tests in this repo" 输出答案后退出,--output-format json 提供可通过管道传递到其他程序的机器可读输出。在 tmux 会话中运行长时间批处理任务,或从 cron 条目启动任务时,使用带 API 密钥的无头模式正合适。但有一个注意事项:cron 任务不会加载任何登录文件。因此,应为 crontab 行单独提供 GEMINI_API_KEY,或让命令加载 ~/.gemini_env;否则运行会因缺少凭据而失败。
在同时运行生产服务的主机上进行沙箱隔离和权限控制
具备 shell 访问权限的代理就等同于拥有 shell。Gemini CLI 可以运行命令,默认会在每个有风险的命令前请求确认,但用户可能会启用 --yolo(自动批准每次工具调用)。这样一来,它就能以运行该 CLI 的用户的完整权限删除文件、推送到 git,或访问内部服务。在同时运行生产服务的主机上,这会造成实际的影响范围,而不是假设性风险。
以下按收益从高到低列出 3 项控制措施:
- 使用专用的非特权用户运行。 不要使用 root,也不要让该用户加入
sudo。创建一个agent用户,为其配置独立的主目录,并在该用户下安装 Node 和 CLI。即使误解了指令,影响也会限制在该账户内。这是价值最高的一项决策。 - 不要将生产凭据放在该主机上。 不要存放生产环境的
~/.aws/credentials,不要从生产环境复制.env,也不要配置对重要资源具有写入权限的数据库密码。应提供 staging 凭据或只读凭据。 - 使用内置沙箱。 安装 Docker 或 Podman 后,
gemini --sandbox(或GEMINI_SANDBOX=docker)会在容器内运行代理的工具调用。该容器只挂载当前项目目录,不会挂载主机文件系统的其余部分。它不能替代非特权用户,但在同一 VPS 承担实际生产工作时,可以作为有效的第二层隔离。
如果你在其他自托管工具旁运行 Gemini CLI,例如使用在同一 VPS 上向代理公开工具的 MCP 服务器,应将每项新增能力都视为代理可访问范围的扩大,并将提供给它的令牌严格限制为单一用途。
配额、费用以及您选择的身份验证路径
身份验证路径决定计费方式;自 2026 年 6 月 18 日起,它还决定您是否能使用该服务。根据 Google 的公告,从这一天起,Gemini CLI 不再为 Google AI Pro 和 Ultra 订阅者提供服务,也不再为免费使用者提供服务。这包括个人账号免费层级和未计费的 API 密钥。通过付费 Gemini API 密钥和 Gemini Enterprise Agent Platform API 密钥仍可使用该服务,费用按令牌计收;拥有 Gemini Code Assist Standard 或 Enterprise 许可证,或具备其他 Google Cloud 访问权限的组织,则通过 Google Cloud 计费。每个层级仍有每分钟和每日限制;超过限制后,请求会返回速率限制错误,直到时间窗口重置。
有两点需要注意。无人值守的代理如果陷入循环,可能会迅速耗尽配额,因此在将其交给 cron 作业运行前,先观察它运行几次。还有,如果您在服务器端运行模型的原因是隐私或不受计量的推理,而不是使用 Google 托管的模型,那么应选择其他工具。使用 Ollama 在 VPS 上自行托管开放式 LLM 可将模型权重和提示保存在您自己的服务器上,但代价是运行的模型会比 Gemini 小得多。
保持更新
Gemini CLI 经常发布新版本。由于您将它安装到了由用户拥有的前缀目录中,更新时无需使用 sudo:
npm install -g @google/gemini-cli@latest
gemini --versionGemini CLI 提供多个发布渠道:@latest 是稳定版,@preview 是每周预览版,@nightly 是最新开发版。对于任何依赖的环境,请固定使用 @latest。使用 nvm 时,全局软件包位于当前激活的 Node 版本目录下,因此执行 nvm use 切换 Node 后,可能需要重新安装 CLI。请阅读发布说明,不要追逐每个补丁版本。
故障模式及准确字符串
npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' },随后 CLI 在运行时崩溃。 Node 版本过旧。发行版提供的是 18.19.1,该版本也已超过生命周期。请从 NodeSource 或 nvm 安装当前 LTS 版本(Node 20 满足 CLI 的最低版本要求,但自 2026 年 4 月起也已超过生命周期),使用 node --version 确认。如果安装了多个 Node,请检查 which node 是否指向新版本,而不是 /usr/bin/node。
npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...'。 这是将全局软件包安装到 root 所有的前缀目录中导致的。不要使用 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://127.0.0.1:PORT。 CLI 找到了显示变量(通常来自 ssh -X),因此使用了回环流程,而回调请求会返回到服务器。运行 NO_BROWSER=true gemini 以使用粘贴代码流程,或使用 API key 流程(GEMINI_API_KEY)。在普通 SSH 会话中,应该改为看到 Enter the authorization code:;请在笔记本电脑的浏览器中批准该 URL,然后粘贴 Google 显示的代码。
SSH 断开后进程消失。 你直接在 SSH shell 中运行了 gemini,因此它是该 shell 的子进程,断开连接时随 pty 一起退出。没有可恢复的进程。每次会话都先启动 tmux new -A -s gemini,然后在其中运行 CLI。
已设置 key,但认证仍然失败,CLI 返回认证选择器,或请求返回带有 HTTP 400 的 API key not valid。 CLI 所处的环境中没有该 key。使用 printenv GEMINI_API_KEY 确认。如果输出为空,说明你的 ~/.gemini_env 从未被加载。检查该行是否位于 ~/.bashrc 中;交互式 shell(包括 tmux)会读取该文件,但 cron 和其他非交互式 shell 不会读取。key 值中多余的空格或引号也会导致 API key not valid。
429 / RESOURCE_EXHAUSTED / 限流消息。 你已达到认证所用层级的配额。等待配额窗口重置,降低 agent 的运行速度,或改用计费 API key。陷入重试循环的 agent 会持续触发此问题。请停止它并检查其行为。
FAQ
如何在无头服务器上完成 Gemini CLI 身份验证?
使用付费 API key,不要使用浏览器登录。在 Google AI Studio 的计费项目中创建 key,将其保存到 shell 会加载的 mode-600 文件中(export GEMINI_API_KEY=...),CLI 就会完全跳过 OAuth 浏览器流程。如果使用 Google 登录,例如使用 Code Assist Standard 或 Enterprise 许可证,CLI 会在无头服务器上显示一个 URL;在笔记本电脑上打开该 URL,完成授权,然后将 Google 显示的代码粘贴回 Enter the authorization code: 提示符。无需固定端口,也无需隧道,但必须有人操作浏览器,因此不适合脚本。自 June 18, 2026 起,Gemini CLI 不再向免费个人账号提供服务。
为什么 npm 全局安装需要 sudo,如何避免?
因为 npm 的默认全局前缀是 /usr/lib/node_modules,当前用户没有写入权限,所以直接运行 npm install -g 会因 EACCES 失败。错误做法是使用 sudo npm -g,这会留下由 root 所有的文件,导致后续安装失败。正确做法是将前缀指向主目录(npm config set prefix ~/.npm-global),并将其 bin 添加到 PATH;也可以使用 nvm,它会自动将全局包安装到主目录下。
如何在断开连接后让 Gemini CLI 继续运行?
在 tmux 中运行它。从 SSH shell 启动的进程是该 shell 的子进程;连接断开时,进程会随之退出。tmux 会在一个脱离终端的服务器中运行 shell,因此连接断开后仍能继续运行。使用 tmux new -A -s gemini,在其中运行 gemini,使用 Ctrl-b d 脱离会话,之后使用 tmux attach -t gemini 重新连接。
在生产服务器上运行 Gemini CLI 安全吗?
只有谨慎配置后才安全,因为拥有 shell 访问权限的代理可以执行运行用户能够执行的任何操作。使用专用的非特权用户运行,不授予 sudo 权限,将生产凭据保留在服务器之外,避免使用 --yolo 自动批准,并使用 --sandbox(Docker 或 Podman)将工具调用与主机隔离。运行该进程的账号比设置的任何单个标志更重要。
使用 Gemini CLI 是否需要开放防火墙端口?
不需要。它是一个向 Google API 发起出站 HTTPS 请求的客户端,因此只需要出站端口 443,不需要入站端口。无头服务器上的 Google 登录同样不需要端口:将代码粘贴回终端即可,无需在服务器上接收回调。保持入站访问限制。