SSD Nodes Learn
Руководства Matt ConnorАвтор: Matt Connor · Обновлено 2026-07-24

Как запустить Gemini CLI на headless VPS

Инструкция по установке Gemini CLI на VPS: актуальная Node, установка npm без sudo и авторизация через API key. Используйте tmux для защиты сессий SSH.

Что вы создаете

Постоянно работающий Gemini CLI на вашем сервере, доступный через SSH. Он будет выполнять длительные задачи агента даже после закрытия вашего ноутбука. Установка состоит из трех команд. Основная сложность заключается в обходе ограничений, связанных с графическим интерфейсом: CLI от Google требует браузер для входа, а на вашем сервере его нет. Поэтому большая часть этого руководства посвящена headless-методу. Вам потребуется актуальная версия Node, которой нет в стандартных репозиториях дистрибутива, глобальная установка npm без прав root, авторизация без браузера с использованием API key (который не попадет в историю команд), а также tmux, чтобы разрыв SSH-сессии не прерывал выполнение задачи.

Gemini CLI — это Node-программа (@google/gemini-cli) с открытым исходным кодом (Apache-2.0). Она взаимодействует с моделями Google Gemini, может читать и записывать файлы, выполнять shell-команды и управлять инструментами в рабочей директории. На VPS это компактный и постоянно доступный агент. Вы можете оставить его работать, поэтому учетная запись, от которой он запускается, и учетные данные на сервере важнее любых остальных настроек в этом руководстве.

Предварительные требования и известные нюансы

  • Чистая Ubuntu 24.04 KVM VPS с правами root или sudo. Подходит любой тарифный план KVM; сам CLI потребляет мало ресурсов, около нескольких сотен MB RAM в состоянии покоя.
  • Node.js версии 20 или новее. Это единственное жесткое ограничение по версии; пакеты из дистрибутива имеют более старую версию — см. следующий раздел.
  • Исходящий HTTPS (порт 443) к Google APIs. Входящие порты не требуются; это клиент, а не сервер, поэтому открывать порты в firewall не нужно.
  • Способ аутентификации, не требующий браузера на сервере: либо API-ключ Gemini из Google AI Studio, либо SSH-туннель к браузеру на вашей локальной машине. Использование API-ключа подходит для скриптов и автоматического запуска.
  • Docker или Podman, только если вам нужна изоляция --sandbox. Опционально, информация приведена в конце.

Нюанс, на котором ошибаются все: стандартный процесс входа gemini при первом запуске предназначен для десктопных систем. Он пытается открыть браузер и на headless-сервере либо выдает ошибку, либо предоставляет нерабочую ссылку. Выберите способ аутентификации до начала работы.

Node: пакет дистрибутива устарел

В репозиториях Ubuntu 24.04 поставляется Node 18.19.1 в связке с npm 9.2.0. В package.json Gemini CLI указана версия 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 будет работать на неподдерживаемой среде выполнения. Это приведет к некорректной работе или сбоям, как только программа обратится к API Node версии 20+, которое ожидается в системе. Кроме того, поддержка Node 18 завершилась в апреле 2025 года, поэтому этот вариант не подходит. Установите актуальную версию LTS перед установкой CLI. Существует два надежных способа: NodeSource (системный подписанный apt-репозиторий) или nvm (менеджер версий для пользователя). Выберите один из них.

NodeSource, если вам нужно, чтобы Node был доступен всем пользователям системы:

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 --version должен выводить v20.x или выше — v24.x является текущей активной LTS. Проверьте страницу NodeSource для получения актуального скрипта установки; в URL-адресе параметр setup_24.x нужно изменить, когда выйдет новая LTS.

nvm, если вы предпочитаете хранить Node в домашнем каталоге пользователя и не использовать sudo:

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

Версия v0.40.1 в этом URL-адресе была актуальна на момент написания статьи; проверьте README nvm для получения последней версии и замените номер версии перед запуском. У nvm есть преимущество для данной задачи: он устанавливает Node и глобальные пакеты в ~/.nvm, поэтому проблема с правами доступа при глобальной установке из следующего раздела не возникнет. Если вы используете nvm, шаг с настройкой npm-prefix можно пропустить.

Установка CLI без sudo npm -g

Команда sudo npm install -g @google/gemini-cli кажется удобной, но не используйте её. Глобальный префикс, принадлежащий root, вызовет ошибки прав доступа при каждой последующей установке. Также в кэше npm останутся файлы, принадлежащие root, что создаст проблемы спустя месяцы. Если запустить обычный (без sudo) npm install -g для системного Node, возникнет другая ошибка:

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 в ваш домашний каталог. Тогда глобальные пакеты будут устанавливаться там, где вы являетесь владельцем:

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 не сработал — см. варианты ошибок. Если вы используете nvm, пропустите строки с префиксом: nvm уже устанавливает глобальные пакеты в ваш домашний каталог.

Если вы ранее запускали sudo npm и теперь видите Your cache folder contains root-owned files, исправьте это с помощью sudo chown -R $(id -u):$(id -g) ~/.npm.

Проблема аутентификации в headless-режиме и способы её решения

При первом интерактивном запуске gemini будет предложено войти через аккаунт Google. На десктопе откроется вкладка браузера. На headless VPS браузера нет, поэтому процесс либо выведет URL-адрес localhost, который нужно открыть вручную, либо завершится ошибкой вида:

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 через переменную окружения; 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 ~/.bashrc

chmod 600 означает, что файл доступен только вашему пользователю. Проверьте, что ключ попал в окружение, с помощью printenv GEMINI_API_KEY; если команда ничего не вывела, CLI попытается использовать браузер и завершится ошибкой. CLI также считывает файл .env в ~/.gemini/, если вы предпочитаете такую структуру — действуют те же правила, поэтому используйте chmod 600 ~/.gemini/.env.

Второй способ позволяет использовать вход через личный аккаунт Google (и его бесплатный уровень), пробросив OAuth callback на ваш ноутбук. Сложность в том, что loopback-сервер 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 для аутентификации. Откройте этот URL в браузере на ноутбуке и подтвердите вход. Когда Google перенаправит вас на http://localhost:8085/..., SSH-туннель доставит запрос на loopback-сервер на VPS, и вход будет завершен. Если не зафиксировать порт, он будет меняться при каждом запуске, и никакой заранее настроенный ssh -L не сможет его перехватить. Этот метод работает, но требует вашего присутствия у браузера, поэтому он не подходит для скриптов. Для любых фоновых процессов используйте API key.

Для Vertex AI или проекта Google Cloud вместо AI Studio установите GOOGLE_API_KEY вместе с GOOGLE_GENAI_USE_VERTEXAI=true, либо GOOGLE_CLOUD_PROJECT для лицензии Code Assist — соблюдайте те же правила работы с переменными окружения и файлами с правами 600.

Запускайте процесс внутри tmux, чтобы разрыв SSH-сессии не прервал его выполнение

Процесс gemini, запущенный напрямую из вашей SSH-оболочки, является ее дочерним процессом. Если соединение будет разорвано — из-за закрытия ноутбука, потери Wi-Fi или тайм-аута бездействия — sshd уничтожит псевдотерминал. Оболочка получит сигнал SIGHUP и завершит работу в CLI. Задача, выполнявшаяся десять минут во время редактирования файлов, будет прервана, и после повторного подключения процесс не восстановится.

tmux решает эту проблему, становясь владельцем оболочки вместо sshd. Это тот же принцип, который используется в запуске AI-агента для написания кода на удаленном VPS внутри tmux, и здесь он работает аналогично:

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, если она существует, или создает новую, если ее нет. Это единственная команда, которую следует выполнять сразу после каждого входа в систему. Оболочка внутри принадлежит отсоединенному (detached) серверу tmux, а не вашей SSH-сессии, поэтому при разрыве соединения CLI продолжает работать. После повторного подключения и выполнения команды attach вы вернетесь в ту же сессию с сохраненным выводом.

Для неинтерактивного запуска в сценариях у Gemini CLI есть безголовый (headless) режим: gemini -p "summarise the failing tests in this repo" выводит ответ и завершает работу, а --output-format json выдает машиночитаемый вывод для передачи через pipe. Безголовый режим с API-ключом — это именно то, что необходимо внутри сессии tmux при выполнении длительных пакетных заданий или при запуске через cron. Есть одно ограничение: задания cron не загружают ваши файлы конфигурации входа, поэтому укажите в строке crontab собственный GEMINI_API_KEY (или добавьте команду source ~/.gemini_env), иначе CLI переключится на браузерный сценарий и завершится с ошибкой.

Песочница и права доступа на сервере с рабочей нагрузкой (production)

Агент с доступом к shell предоставляет доступ к командной строке. Gemini CLI может выполнять команды. По умолчанию он запрашивает подтверждение перед каждым рискованным действием. Однако пользователи часто включают --yolo (автоматическое одобрение всех вызовов инструментов). В этом случае агент может удалять файлы, отправлять изменения в git или обращаться к внутренним сервисам с правами текущего пользователя. На сервере, где запущен production, это создает реальную зону поражения, а не гипотетическую.

Три меры контроля в порядке их эффективности:

  • Запуск от имени выделенного непривилегированного пользователя. Не root и не участник группы sudo. Создайте пользователя agent с собственным домашним каталогом, установите Node и CLI в него. В этом случае ошибка в инструкции ограничит действия только этим аккаунтом. Это самое важное решение.
  • Отсутствие учетных данных production на сервере. Никаких prod ~/.aws/credentials, никаких скопированных из production .env, никаких паролей к базам данных с правами записи к важным данным. Предоставьте агенту учетные данные для staging или права только на чтение.
  • Использование встроенной песочницы. При установленных Docker или Podman, gemini --sandbox (или GEMINI_SANDBOX=docker) запускает вызовы инструментов агента внутри контейнера, изолированного от файловой системы и сети хоста. Это не заменяет использование непривилегированного пользователя, но служит надежным вторым уровнем защиты, если на этом же VPS выполняются важные задачи.

Если вы запускаете Gemini CLI рядом с другими self-hosted инструментами — например, MCP server, предоставляющий инструменты агенту на том же VPS, — рассматривайте каждую новую функцию как расширение поверхности атаки. Ограничивайте область применения токенов только одной конкретной задачей.

Квоты, стоимость и выбранный способ аутентификации

Способ аутентификации определяет порядок тарификации. Личный аккаунт Google (через OAuth) использует бесплатный уровень Gemini Code Assist с ограничениями по количеству запросов в минуту и в день. При превышении этих лимитов запросы будут возвращать ошибку rate-limit до сброса окна лимитов. API key из AI Studio может быть бесплатным или платным в зависимости от проекта; платный ключ увеличивает лимиты и тарифицируется за каждый token. Аутентификация через Vertex и Cloud-project осуществляется через Google Cloud.

Два практических замечания. Автономный агент в цикле может быстро исчерпать квоту, поэтому первые запуски следует контролировать перед переносом задачи в cron. Если вам нужна серверная модель из соображений конфиденциальности или для безлимичного вывода (вместо использования хостинг-моделей Google), используйте другой инструмент — самостоятельный хостинг open LLM с помощью Ollama на VPS позволяет хранить веса и промпты на вашем собственном сервере, но требует использования гораздо менее мощной модели, чем Gemini.

Обновление системы

Gemini CLI часто выпускает обновления. Поскольку вы установили его в пользовательский префикс, для обновлений не требуется sudo:

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

Существуют каналы выпуска: @latest — стабильная версия, @preview — еженедельная предварительная версия, @nightly — самая ранняя версия (bleeding edge). Для критически важных систем используйте канал @latest. В nvm глобальные пакеты привязаны к активной версии Node, поэтому после выполнения nvm use для переключения версии Node может потребоваться переустановка CLI. Рекомендуется изучать примечания к выпуску (release notes), а не устанавливать каждый патч.

Failure modes, with the exact strings

npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' }, then the CLI crashing at runtime. Node is too old — the distro's 18.19.1, which is also past end-of-life. Install Node 20+ from NodeSource or nvm, confirm with node --version, and if you have several Nodes installed, check which node points at the new one and not /usr/bin/node.

npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...'. A global install into a root-owned prefix. Do not sudo it — set npm config set prefix ~/.npm-global, put ~/.npm-global/bin on PATH, and reinstall as your normal user. If an earlier sudo npm left root-owned cache files (Your cache folder contains root-owned files), run sudo chown -R $(id -u):$(id -g) ~/.npm.

Failed to open browser, a login that hangs, or a redirect_uri=http://localhost:PORT you cannot reach. The OAuth flow wants a browser the server does not have, and its localhost callback points at the server, not your laptop. Use the API-key path (GEMINI_API_KEY), or pin OAUTH_CALLBACK_PORT, forward it over SSH with ssh -L, and open the URL locally.

The process vanished when SSH dropped. You ran gemini straight from the SSH shell, so it was a child of that shell and died with the pty on disconnect. Nothing to recover. Start every session with tmux new -A -s gemini and run the CLI inside it.

Auth still fails with the key set — the CLI drops back to its auth picker, or a request returns API key not valid with HTTP 400. The key is not in the environment the CLI sees. Confirm with printenv GEMINI_API_KEY; if it is empty, your ~/.gemini_env was never sourced — check the line is in ~/.bashrc, which interactive shells (tmux included) read but cron and other non-interactive shells do not. A stray space or quote inside the key value also produces API key not valid.

429 / RESOURCE_EXHAUSTED / a rate-limit message. You hit the quota for whichever tier your auth uses. Wait for the window to reset, slow the agent down, or move to a billed API key. An agent stuck in a retry loop keeps hitting this — stop it and check what it is doing.

FAQ

Как аутентифицировать Gemini CLI на сервере без монитора?

Используйте API key вместо входа через браузер. Создайте ключ в Google AI Studio, поместите его в файл с правами mode-600, который загружается вашей оболочкой (export GEMINI_API_KEY=...), и CLI полностью пропустит процесс OAuth в браузере. Если вам необходим бесплатный уровень с персональным аккаунтом, закрепите loopback-порт с помощью OAUTH_CALLBACK_PORT=8085, пробросьте его на ваш ноутбук через ssh -L 8085:localhost:8085 user@server и откройте выведенный URL локально. Этот метод требует вашего присутствия в браузере, поэтому он не подходит для скриптов.

Почему npm global install требует 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-сессии, завершается при разрыве соединения, так как он является дочерним процессом этой сессии. tmux запускает оболочку через отсоединенный (detached) сервер, который продолжает работать после отключения. Используйте tmux new -A -s gemini, запустите gemini внутри, отсоединитесь с помощью Ctrl-b d и подключитесь снова позже с помощью tmux attach -t gemini.

Безопасно ли запускать Gemini CLI на продуктивном сервере?

Только при соблюдении осторожности, так как агент с доступом к shell может выполнять любые действия, доступные пользователю, от имени которого он запущен. Запускайте его от имени отдельного непривилегированного пользователя без прав sudo, не храните на машине продуктивные учетные данные, избегайте автоматического подтверждения --yolo и используйте --sandbox (Docker или Podman) для изоляции вызовов инструментов от хост-системы. Учетная запись, от которой запускается процесс, важнее любого установленного флага.

Нужно ли открывать порты в firewall для Gemini CLI?

Нет. Это клиент, который выполняет исходящие HTTPS-запросы к API Google, поэтому ему нужен исходящий порт 443, но не требуются входящие порты. Если вы используете туннель OAuth, закрепленный порт обратного вызова (например, 8085) работает на localhost и доступен через ваш SSH-проброс, а не через открытый входящий порт. Оставьте входящие порты закрытыми.

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