Как запустить Gemini CLI на headless VPS
Пошаговая настройка Gemini CLI на сервере без браузера. Вы узнаете, как установить свежий Node.js, настроить API-ключ без прав root и использовать tmux для фоновых задач.
Что вы создаёте
Постоянно работающий Gemini CLI на вашем собственном сервере, доступный по SSH, который выполняет длительные задачи агента, продолжающиеся после закрытия ноутбука. Установка состоит из трёх команд. Сложность заключается в том, что обычно такие инструменты рассчитаны на десктоп: CLI от Google требует открытия браузера для входа, а на сервере его нет. Поэтому большая часть этого руководства посвящена работе в headless-режиме: установке актуальной версии Node, которую не предоставляет дистрибутив, глобальной установке npm без прав root, аутентификации без браузера с использованием API-ключа, который не попадает в историю командной оболочки, и использованию tmux, чтобы разрыв SSH-сессии не прерывал выполнение задачи.
Gemini CLI — это программа на Node с открытым исходным кодом (Apache-2.0) (@google/gemini-cli), которая взаимодействует с моделями Gemini от Google, умеет читать и записывать файлы, выполнять команды оболочки и запускать инструменты в рабочей директории. На VPS это компактный и всегда доступный агент, который можно оставить в фоновом режиме. Именно поэтому учётная запись, от имени которой он работает, и учётные данные, хранящиеся на сервере, важнее любого отдельного параметра настройки.
Предварительные требования и типичные сложности
- Свежий VPS на базе Ubuntu 24.04 с виртуализацией KVM и доступом root или sudo. Подойдет любой тариф KVM; сам CLI потребляет мало ресурсов, в состоянии покоя занимая несколько сотен МБ оперативной памяти.
- Node.js версии 20 или новее. Это жесткое требование к версии, а пакет из репозитория дистрибутива ему не соответствует (см. следующий раздел).
- Исходящий HTTPS-трафик (порт 443) к API Google. Входящие порты не требуются; это клиент, а не сервер, поэтому открывать порты в межсетевом экране не нужно.
- Способ аутентификации, не требующий браузера на сервере: либо ключ Gemini API из Google AI Studio, либо SSH-туннель к браузеру на вашей локальной машине. Использование API-ключа — предпочтительный вариант для скриптов и автоматизированного запуска.
- Docker или Podman, только если вам требуется изоляция
--sandbox. Опционально, рассматривается ближе к концу руководства.
Сложность, с которой сталкиваются все: стандартный процесс первого входа gemini рассчитан на работу в графической среде. Он пытается открыть браузер, что на headless-сервере приводит либо к ошибке, либо к выдаче нерабочей ссылки. Определитесь со способом аутентификации до начала работы.
Примечание: пакет в дистрибутиве слишком старый
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 для получения актуального скрипта настройки; setup_24.x в URL — это часть, которую нужно изменить при выходе новой версии 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, которые вызовут проблемы спустя месяцы. Запуск обычной команды npm install -g (без sudo) для системного 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, который считывает ~/.bashrc и пропускает ~/.profile. Поэтому строка PATH в неверном файле сделает gemini невидимым именно там, где он вам нужен. Вывод номера версии командой gemini --version — это полная проверка. Если вместо этого вы получаете gemini: command not found, значит, ваш экспорт PATH не применился; ознакомьтесь с режимами сбоя. При использовании 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 через переменную окружения; программа считывает GEMINI_API_KEY и полностью пропускает этап с браузером. Теперь о том, как не допустить попадания ключа в историю команд и файлы, доступные другим пользователям. Не вводите export GEMINI_API_KEY=AIza... в командной строке, так как это сохранит ключ в открытом виде в ~/.bash_history, и не записывайте его в файл с открытыми правами доступа. Запишите его в файл с правами 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 переключится на браузерный поток и завершится ошибкой. Программа также считывает файл .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
geminiCLI не может открыть браузер, поэтому он выводит 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, если она существует, или создает её, если нет. Это единственная команда, которую стоит выполнять сразу после каждого входа в систему. Оболочка внутри принадлежит отсоединенному серверу tmux, а не вашей SSH-сессии, поэтому разрыв соединения не останавливает работу CLI. При повторном подключении вы присоединяетесь к сессии и возвращаетесь к тому же состоянию терминала. Если вы запускаете несколько сессий агента на одном сервере, по одной на каждую сессию tmux, они не смогут взаимодействовать друг с другом, в отличие от Claude Code, где одна сессия может передавать текст другой на том же VPS. Поэтому держите каждое задание Gemini независимым или координируйте их через файлы на диске.
Для неинтерактивных скриптовых запусков у Gemini CLI есть headless-режим: gemini -p "summarise the failing tests in this repo" выводит ответ и завершает работу, а --output-format json предоставляет машиночитаемый вывод для передачи в другие инструменты. Headless-режим с API-ключом — это именно то, что нужно для длительных пакетных заданий внутри tmux или при запуске из cron. Учтите один нюанс: задание cron не считывает ваши файлы инициализации оболочки, поэтому укажите в строке crontab переменную GEMINI_API_KEY (или настройте команду на считывание ~/.gemini_env), иначе CLI попытается запустить процесс авторизации через браузер и завершится с ошибкой.
Песочницы и права доступа на сервере с рабочими сервисами
Агент с доступом к оболочке — это и есть оболочка. Gemini CLI может выполнять команды, и по умолчанию он запрашивает подтверждение перед каждым потенциально опасным действием. Однако пользователи часто прибегают к --yolo (автоматическое одобрение всех вызовов инструментов), после чего агент получает возможность удалять файлы, отправлять изменения в git или обращаться к внутренним сервисам с полными правами пользователя, от имени которого он запущен. На сервере, где работают реальные приложения, это создает реальную угрозу безопасности, а не гипотетическую.
Три уровня контроля, отсортированные по эффективности:
- Запуск от имени выделенного пользователя с ограниченными правами. Не используйте root и не добавляйте пользователя в группу
sudo. Создайте пользователяagentс собственным домашним каталогом, установите Node и CLI в него. В этом случае последствия неверно интерпретированной команды будут ограничены рамками этой учетной записи. Это самое важное решение для обеспечения безопасности. - Исключите рабочие учетные данные на сервере. Не храните там рабочие
~/.aws/credentials, не копируйте.envс продакшена и не используйте пароли от баз данных с правами на запись для критически важных ресурсов. Используйте учетные данные для тестовой среды или с доступом только для чтения. - Используйте встроенную песочницу. Если установлены Docker или Podman,
gemini --sandbox(илиGEMINI_SANDBOX=docker) выполняет вызовы инструментов агента внутри контейнера, изолированного от файловой системы и сети хоста. Это не заменяет запуск от непривилегированного пользователя, но служит надежным вторым уровнем защиты, если на том же VPS работают реальные сервисы.
Если вы запускаете Gemini CLI рядом с другими self-hosted инструментами, например, MCP-сервером, предоставляющим агенту инструменты на том же VPS, рассматривайте каждую добавленную возможность как расширение поверхности атаки, доступной агенту. Ограничивайте токены, которые вы ему передаете, рамками одной конкретной задачи.
Квоты, стоимость и выбор пути аутентификации
Путь аутентификации определяет порядок оплаты. Личная учетная запись Google (путь OAuth) использует бесплатный уровень Gemini Code Assist с жесткими лимитами в минуту и в день; при их превышении запросы возвращают ошибку rate-limit до сброса временного окна. API key из AI Studio может быть бесплатным или платным в зависимости от проекта; платный ключ повышает лимиты и тарифицирует использование по токенам. Аутентификация через Vertex и Cloud-project тарифицируется через Google Cloud.
Два практических замечания. Автономный агент в цикле может быстро исчерпать квоту, поэтому следите за ним первые несколько раз, прежде чем доверять ему выполнение задач через cron. Если ваша цель при использовании серверной модели — конфиденциальность или безлимитный инференс, а не облачные модели Google, то это задача для другого инструмента: самостоятельный хостинг открытой LLM с помощью Ollama на VPS позволяет хранить веса и промпты на вашем собственном сервере, но требует использования значительно менее мощной модели, чем Gemini.
Поддержание актуальной версии
Gemini CLI выпускается часто. Поскольку вы установили его в префикс, принадлежащий пользователю, для обновлений никогда не требуется sudo:
npm install -g @google/gemini-cli@latest
gemini --versionСуществуют каналы релизов: @latest — стабильный, @preview — еженедельная предварительная версия, @nightly — экспериментальная версия. Для всего, от чего вы зависите, фиксируйте версию на @latest. В nvm глобальные пакеты находятся внутри активной версии Node, поэтому после nvm use для переключения Node вам может потребоваться переустановка CLI. Читайте примечания к релизу, вместо того чтобы устанавливать каждый патч.
Режимы сбоев и соответствующие им сообщения
npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' }, а затем аварийное завершение CLI во время выполнения. Версия Node слишком старая, в дистрибутиве используется 18.19.1, срок поддержки которой истёк. Установите Node 20+ из NodeSource или через nvm, подтвердите версию командой 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://localhost:PORT, к которому нет доступа. Процесс OAuth требует браузер, которого нет на сервере, а callback на localhost указывает на сам сервер, а не на ваш ноутбук. Используйте путь через API-ключ (GEMINI_API_KEY) или зафиксируйте OAUTH_CALLBACK_PORT, пробросьте его через SSH с помощью ssh -L и откройте URL локально.
Процесс исчез после разрыва SSH-соединения. Вы запустили gemini напрямую из SSH-оболочки, поэтому он стал дочерним процессом этой оболочки и завершился вместе с pty при отключении. Восстановить его нельзя. Начинайте каждую сессию с tmux new -A -s gemini и запускайте CLI внутри неё.
Аутентификация не проходит при установленном ключе, CLI возвращается к выбору метода входа или запрос возвращает API key not valid с HTTP 400. Ключ отсутствует в окружении, которое видит CLI. Проверьте это с помощью printenv GEMINI_API_KEY; если переменная пуста, ваш файл ~/.gemini_env не был загружен. Убедитесь, что строка добавлена в ~/.bashrc, который считывается интерактивными оболочками (включая tmux), но не считывается cron и другими неинтерактивными оболочками. Лишний пробел или кавычка внутри значения ключа также вызывают API key not valid.
429 / RESOURCE_EXHAUSTED / сообщение об ограничении частоты запросов (rate-limit). Вы превысили квоту для вашего уровня аутентификации. Дождитесь сброса окна ограничений, снизьте интенсивность работы агента или перейдите на платный API-ключ. Агент, застрявший в цикле повторных попыток, продолжает расходовать лимит; остановите его и проверьте, что именно он выполняет.
FAQ
Как аутентифицировать Gemini CLI на сервере без графического интерфейса?
Используйте API key, а не вход через браузер. Создайте ключ в Google AI Studio, сохраните его в файле с правами 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 запускает оболочку внутри отсоединенного сервера, который продолжает работу после отключения. Используйте tmux new -A -s gemini, запустите gemini внутри, отсоединитесь с помощью Ctrl-b d и вернитесь к сессии позже командой tmux attach -t gemini.
Безопасно ли запускать Gemini CLI на production-сервере?
Только при соблюдении мер предосторожности, так как агент с доступом к оболочке может выполнять любые действия от имени пользователя, под которым он запущен. Запускайте его от имени выделенного непривилегированного пользователя без прав sudo, не храните на сервере production-учетные данные, избегайте автоматического подтверждения через --yolo и используйте --sandbox (Docker или Podman) для изоляции вызовов инструментов от хостовой системы. Учетная запись, под которой работает процесс, важнее любого отдельного флага.
Нужно ли открывать порты в файрволе для Gemini CLI?
Нет. Это клиент, который выполняет исходящие HTTPS-запросы к API Google, поэтому ему нужен только исходящий порт 443, входящие порты не требуются. Если вы используете туннель OAuth, зафиксированный порт обратного вызова (например, 8085) работает на localhost и доступен через ваш SSH-проброс, а не через открытый входящий порт. Держите входящие порты закрытыми.