Як запустити Gemini CLI на headless VPS
Налаштування Gemini CLI на VPS: встановлення Node без 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 це компактний агент, який можна залишити працювати. Саме тому обліковий запис, від імені якого він запускається, та облікові дані на сервері є важливішими за будь-яке окреме налаштування в цьому посібнику.
Prerequisites and the honest gotchas
- Чиста Ubuntu 24.04 KVM VPS з правами root або sudo. Підійде будь-який KVM план; сам CLI споживає мало ресурсів, близько кількох сотень MB RAM у стані спокою.
- Node.js 20 або новіша версія. Це єдина жорстка вимога до версії; пакет у дистрибутиві старіший — див. наступний розділ.
- Вихідний HTTPS (порт 443) до Google APIs. Вхідні порти не потрібні; це клієнт, а не сервер, тому відкривати порти у firewall не потрібно.
- Спосіб автентифікації, що не потребує браузера на сервері: або Gemini API key з Google AI Studio, або SSH tunnel до браузера на вашому локальному пристрої. Використання API-key краще підходить для скриптів та автоматичного запуску.
- Docker або Podman, лише якщо вам потрібна ізоляція
--sandbox. Опціонально, описано наприкінці.
Помилка, на якій всі потрапляють: стандартний процес логіну gemini розроблено для desktop-систем. Він намагається відкрити браузер, що на headless-сервері призводить до помилки або видає непрацюче посилання. Виберіть спосіб автентифікації перед початком роботи.
Node: пакет дистрибутива застарілий
Ubuntu 24.04 постачає Node 18.19.1 зі власних репозиторіїв разом із npm 9.2.0. Gemini CLI заявляє engines: { node: ">=20" } через package.json, а 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 також завершив цикл підтримки (end-of-life) у квітні 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 --versionnode --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 призводить до помилок доступу під час кожного наступного встановлення. Також це залишає файли, що належать root, у кеші npm, що спричинить проблеми через кілька місяців. Виконання звичайного (без 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 ~/.bashrcchmod 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
geminiCLI не може відкрити браузер, тому він виводить URL для авторизації; відкрийте його у браузері на ноутбуці та підтвердіть доступ. Коли Google перенаправить вас на http://localhost:8085/..., SSH-прокидання доставить запит на loopback-сервер на VPS, і авторизація завершиться. Якщо не фіксувати порт, він буде змінюватися при кожному запуску, і жоден попередньо налаштований ssh -L не зможе його перехопити. Цей метод працює, але потребує вашої участі через браузер, тому він не підходить для скриптів. Для будь-яких фонових процесів використовуйте API key.
Для Vertex AI або Google Cloud project замість AI Studio встановіть GOOGLE_API_KEY разом із GOOGLE_GENAI_USE_VERTEXAI=true, або GOOGLE_CLOUD_PROJECT для ліцензії Code Assist — дотримуйтесь тих самих правил роботи зі змінними середовища та файлами з правами 600.
Запускайте процес у tmux, щоб розірваний SSH-сеанс не перервав його
Процес gemini, запущений безпосередньо через SSH-оболонку, є її дочірнім процесом. Якщо з'єднання розірветься — через закриття ноутбука, зникнення Wi-Fi або тайм-аут очікування — sshd видалить псевдотермінал. Оболонка отримає сигнал SIGHUP і завершить роботу. Якщо завдання виконувалося 10 хвилин під час редагування файлів, воно припиниться, і після повторного підключення процес неможливо буде відновити.
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 geminitmux 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 (або змусьте команду завантажити ~/.gemini_env), інакше CLI перейде у режим браузера і завершиться помилкою.
Sandboxing та права доступу на хості з продуктивними навантаженнями
Агент із доступом до shell є оболонкою. Gemini CLI може виконувати команди, і за замовчуванням він запитує підтвердження перед кожною ризикованою дією. Проте користувачі часто використовують --yolo (автоматичне підтвердження кожного виклику інструменту), через що агент може видаляти файли, робити git push або звертатися до внутрішніх сервісів з повними правами поточного користувача. На хості, де також працює production, це створює реальну зону ризику, а не гіпотетичну.
Три методи контролю у порядку їхньої ефективності:
- Запуск від імені виділеного непривілейованого користувача. Не root і не член групи
sudo. Створіть користувачаagentз власним home-каталогом, встановіть Node та CLI саме там; тоді помилкова команда залишиться в межах цього облікового запису. Це найважливіше рішення. - Відсутність продуктивних облікових даних на хості. Жодних prod
~/.aws/credentials, жодних.env, скопійованих з production, жодних паролів до баз даних із правами на запис до критичних об'єктів. Надайте агенту облікові дані для staging або лише для читання. - Використання вбудованого пісочниці (sandbox). Якщо встановлено 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 може бути безкоштовним або платним залежно від проєкту — платний ключ збільшує ліміти та стягує плату за кожен токен. Автентифікація через Vertex та Cloud-project здійснюється через Google Cloud.
Дві практичні примітки. Автономний агент у циклі може швидко вичерпати квоту, тому перевірте його роботу перші кілька разів перед тим, як запускати через cron job. І якщо ваша мета використання моделі на стороні сервера — це конфіденційність або безлімітний вивід (inference), а не використання хостингових моделей Google, то вам потрібен інший інструмент — self-hosting an open LLM with Ollama on a VPS зберігає ваги та промпти на вашому власному сервері, але це вимагає запуску набагато меншої моделі, ніж Gemini.
Keeping it updated
Gemini CLI часто випускає оновлення. Оскільки ви встановили його в префікс, що належить користувачу, для оновлення не потрібен sudo:
npm install -g @google/gemini-cli@latest
gemini --versionІснують канали релізів: @latest — стабільний, @preview — щотижневий preview, @nightly — найновіші зміни (bleeding edge). Для критично важливих систем використовуйте @latest. У nvm глобальні пакети прив'язані до активної версії Node, тому після nvm use для перемикання версії Node може знадобитися повторне встановлення CLI. Краще читати release notes, ніж перевіряти кожен патч.
Режими відмови та відповідні рядки
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 на headless-сервері?
Використовуйте API key замість входу через браузер. Створіть ключ у Google AI Studio, помістіть його у файл mode-600, який завантажує ваш shell (export GEMINI_API_KEY=...), і CLI повністю пропустить процес OAuth через браузер. Якщо вам потрібен безкоштовний рівень для особистих акаунтів, зафіксуйте loopback-порт за допомогою OAUTH_CALLBACK_PORT=8085, прокиньте його на ваш ноутбук через ssh -L 8085:localhost:8085 user@server і відкрийте наведений URL локально. Цей метод потребує вашої участі в браузері, тому він не підходить для скриптів.
Чому npm global install потребує sudo і як цього уникнути?
Це стається тому, що стандартний global prefix у npm — /usr/lib/node_modules, на який ваш користувач не має прав запису, тому звичайний npm install -g завершується помилкою EACCES. Неправильним рішенням є sudo npm -g, оскільки це створює файли з правами root, що заважатиме наступним інсталяціям. Правильне рішення — змінити prefix на ваш home-каталог (npm config set prefix ~/.npm-global) і додати його bin до PATH, або використовувати nvm, який автоматично встановлює global-пакети у ваш home.
Як змусити Gemini CLI працювати після розриву з'єднання?
Запускайте його всередині tmux. Процес, запущений через SSH-сесію, завершується при розриві зв'язку, оскільки він є дочірнім процесом цієї сесії; tmux запускає shell під керуванням detached-сервера, який працює після розриву з'єднання. Використовуйте tmux new -A -s gemini, запустіть gemini всередині, від'єднайтеся за допомогою Ctrl-b d і підключіться знову пізніше через tmux attach -t gemini.
Чи безпечно запускати Gemini CLI на production-сервері?
Тільки за умови дотримання обережності, оскільки агент із доступом до shell може виконувати будь-які дії від імені поточного користувача. Запускайте його від імені окремого непривілейненого користувача без прав sudo, не зберігайте production-credentials на цій машині, уникайте автоматичного підтвердження --yolo і використовуйте --sandbox (Docker або Podman) для ізоляції викликів інструментів від хост-системи. Права акаунта, під яким працює CLI, є важливішими за будь-який встановлений прапор.
Чи потрібно відкривати порти у firewall для Gemini CLI?
Ні. Це клієнт, який виконує вихідні HTTPS-запити до Google APIs, тому йому потрібен лише вихідний порт 443; вхідні порти не потрібні. Якщо ви використовуєте OAuth-тунель, зафіксований callback-порт (наприклад, 8085) працює на localhost і доступний через ваш SSH forward, а не через відкритий вхідний порт. Залишайте вхідні порти закритими.