SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor · Atualizado 2026-08-24

Como rodar o Gemini CLI em um VPS sem interface gráfica

Aprenda a rodar o Gemini CLI em um VPS headless: Node atual, instalação global npm sem sudo, autenticação por API key e tmux contra quedas do SSH.

O que você vai criar

Um Gemini CLI sempre ativo num servidor que controla, acessível por SSH, a executar tarefas longas de agentes que continuam a trabalhar depois de fechar o portátil. A instalação resume-se a três comandos. O trabalho está no que pressupõe um desktop: a CLI da Google tenta abrir um navegador para iniciar sessão, mas o servidor não tem nenhum. Por isso, a maior parte deste guia aborda o procedimento sem interface gráfica, uma versão atual do Node que a distribuição não fornece, uma instalação global do npm que não requer root, a autenticação sem navegador com uma chave de API mantida fora do histórico da shell e o tmux, para que uma sessão SSH interrompida não termine uma tarefa em execução.

O Gemini CLI é um programa Node de código aberto (Apache-2.0) (@google/gemini-cli) que comunica com os modelos Gemini da Google e pode ler e escrever ficheiros, executar comandos da shell e utilizar ferramentas no diretório de trabalho. Num VPS, é um agente pequeno e sempre disponível que pode deixar a trabalhar. Por isso, a conta usada para o executar e as credenciais armazenadas no servidor são mais importantes do que qualquer definição isolada deste guia.

Pré-requisitos e limitações importantes

  • Um VPS KVM Ubuntu 24.04 novo, com root ou sudo. Qualquer plano KVM funciona; a CLI é leve e consome algumas centenas de MB de RAM em repouso.
  • Node.js 20 ou mais recente. Este é o único requisito mínimo rígido de versão, e o pacote da distribuição é anterior a essa versão; consulte a próxima seção.
  • HTTPS de saída (porta 443) para as APIs da Google. Não são necessárias portas de entrada; este é um cliente, não um servidor, portanto não é preciso abrir uma exceção na firewall.
  • Uma forma de autenticação que não exija um navegador no servidor: uma chave da API Gemini do Google AI Studio ou um túnel SSH até um navegador no seu próprio computador. O uso da chave da API é a opção adequada para scripts e execuções não interativas.
  • Docker ou Podman, apenas se quiser o isolamento --sandbox. É opcional e explicado perto do fim.

A limitação que apanha toda a gente: o fluxo de início de sessão inicial do gemini foi criado para um desktop. Tenta abrir um navegador e, num sistema sem interface gráfica, pode falhar ou fornecer uma ligação que não funciona. Decida o método de autenticação antes de começar.

Node: o pacote da distribuição é demasiado antigo

O Ubuntu 24.04 disponibiliza o Node 18.19.1 nos seus próprios repositórios, associado ao npm 9.2.0. O package.json da Gemini CLI declara engines: { node: ">=20" }, mas o npm não interrompe por predefinição quando encontra uma incompatibilidade. Continua a instalação e apresenta um aviso que identifica a diferença:

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 }

Se ignorar esse aviso, a CLI será executada num runtime não suportado. Poderá comportar-se incorretamente ou falhar assim que utilizar uma API do Node 20+ que deveria estar disponível. O Node 18 também chegou ao fim de vida em abril de 2025, portanto não é uma solução viável. Instale uma versão LTS atual antes de instalar a CLI. Existem duas opções adequadas: NodeSource, um repositório apt assinado e disponível em todo o sistema, ou nvm, um gestor de versões por utilizador. Escolha uma.

NodeSource, se quiser disponibilizar o Node a todos os utilizadores do sistema:

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 deve apresentar v20.x ou superior. v24.x é a LTS atualmente ativa. Consulte a página do NodeSource para obter o script de configuração atual. O setup_24.x no URL é o valor que deve atualizar quando for lançada uma LTS mais recente.

nvm, se preferir manter o Node no diretório pessoal de um utilizador e nunca o executar com sudo:

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

O v0.40.1 nesse URL era o valor atual quando este texto foi escrito. Consulte o README do nvm para obter a versão mais recente e substitua a versão antes de executar o comando. O nvm tem uma vantagem importante neste caso: instala o Node e os respetivos pacotes globais em ~/.nvm. Assim, o problema de permissões durante a instalação global descrito na secção seguinte não ocorre. Se escolher nvm, pode ignorar o passo de configuração do prefixo do npm.

Instale a CLI sem sudo npm -g

O comando tentador é sudo npm install -g @google/gemini-cli. Não o execute. Um prefixo global pertencente a root causa erros de permissões em todas as instalações seguintes e deixa ficheiros pertencentes a root na cache do npm, o que pode causar problemas meses mais tarde. Se executar um npm install -g simples, sem sudo, contra um Node do sistema, terá o outro erro:

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'

O npm está a tentar escrever em /usr/lib, onde o seu utilizador não tem permissões. A correção não é usar sudo. Defina o prefixo global do npm para o seu diretório pessoal, para que as instalações globais sejam feitas num local que lhe pertence:

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, e não ~/.profile, é intencional. O tmux, que executará a CLI dentro de duas secções, inicia uma shell que não é de login. Essa shell lê ~/.bashrc e ignora ~/.profile. Por isso, uma linha PATH no ficheiro errado deixa gemini invisível exatamente onde precisa dele. gemini --version imprimir um número de versão é o teste completo. Se obtiver gemini: command not found, a exportação de PATH não foi aplicada. Consulte as formas de falha. No nvm, ignore totalmente as linhas do prefixo. O nvm já instala os pacotes globais no seu diretório pessoal.

Se executou sudo npm anteriormente e agora vê Your cache folder contains root-owned files, corrija o problema uma vez com sudo chown -R $(id -u):$(id -g) ~/.npm.

O problema da autenticação sem interface gráfica e como o contornar

Execute gemini de forma interativa na primeira vez. O comando disponibiliza o início de sessão com a sua conta Google. Num desktop, abre um separador do navegador. Num VPS headless, não existe navegador. Por isso, o fluxo imprime um URL de localhost que espera que abra ou falha diretamente com algo semelhante a:

Failed to open browser. Please visit the following URL to authorize:
https://accounts.google.com/o/oauth2/v2/auth?...&redirect_uri=http://localhost:PORT

O problema está no redirect_uri=http://localhost:PORT. Mesmo que abra esse URL no seu portátil e autorize o acesso, o Google redireciona para http://localhost:PORT, ou seja, para o localhost no servidor. Nenhuma aplicação no seu portátil consegue alcançar essa porta. O início de sessão nunca é concluído.

Existem duas formas corretas de resolver o problema.

A primeira é usar uma chave de API. Esta é a opção padrão adequada para um servidor. Crie uma chave no Google AI Studio (aistudio.google.com) e disponibilize-a à CLI através de uma variável de ambiente. A CLI lê GEMINI_API_KEY e ignora completamente o fluxo do navegador. Agora, quanto a manter a chave fora do histórico e de ficheiros legíveis por todos: não introduza export GEMINI_API_KEY=AIza... na prompt. O valor fica gravado em texto simples em ~/.bash_history. Também não o coloque num ficheiro que outros utilizadores possam ler. Grave-o num ficheiro com modo 600 que a shell carregue no arranque:

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 significa que apenas o seu utilizador pode ler o ficheiro. Confirme que a chave chegou ao ambiente com printenv GEMINI_API_KEY. Se o comando não imprimir nada, a CLI recorre ao fluxo do navegador e falha. A CLI também lê um ficheiro .env em ~/.gemini/, se preferir essa organização. A mesma regra aplica-se nesse caso: chmod 600 ~/.gemini/.env.

A segunda forma mantém o início de sessão com a conta Google pessoal, incluindo o respetivo nível gratuito, através de um túnel que encaminha o callback OAuth de volta para o seu portátil. O problema é que o servidor loopback da CLI usa uma porta aleatória em cada execução. Não existe uma porta estável para encaminhar, a menos que a fixe primeiro com a variável de ambiente OAUTH_CALLBACK_PORT. Depois, encaminhe exatamente essa porta:

# 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

A CLI não consegue abrir um navegador, por isso imprime o URL de autenticação. Abra-o no navegador do seu portátil e autorize o acesso. Quando o Google redirecionar para http://localhost:8085/..., o encaminhamento SSH transportará o pedido para o servidor loopback no VPS e o início de sessão será concluído. Se não fixar a porta, será usada uma nova porta aleatória em cada execução. Nenhum ssh -L configurado antecipadamente conseguirá intercetar essa ligação. O método funciona, mas exige que esteja junto de um navegador. Por isso, não é adequado para scripts. Para qualquer processo que deva permanecer em execução, use a chave de API.

Para usar Vertex AI ou um projeto Google Cloud em vez do AI Studio, defina GOOGLE_API_KEY juntamente com GOOGLE_GENAI_USE_VERTEXAI=true, ou GOOGLE_CLOUD_PROJECT para uma licença Code Assist. Aplique as mesmas regras para variáveis de ambiente e use um ficheiro com modo 600.

Execute dentro do tmux para que uma sessão SSH interrompida não encerre o processo

Um processo gemini iniciado diretamente a partir da shell SSH é filho dessa shell. Se perder a ligação, fechar o portátil, a rede Wi-Fi cair ou ocorrer um timeout de inatividade, o sshd destrói o pseudo-terminal, a shell recebe SIGHUP e, por sua vez, encerra o processo CLI. Uma tarefa que esteja há dez minutos a editar ficheiros termina nesse momento e, ao voltar a ligar-se, não há nenhum processo para recuperar.

O tmux resolve este problema ao assumir o controlo da shell, em vez de ser controlado por sshd. Este é o mesmo padrão de executar um agente de programação com IA num VPS remoto dentro do tmux e funciona da mesma forma aqui:

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 liga-se a uma sessão chamada gemini se ela existir e cria-a caso contrário. Por isso, é o comando a executar imediatamente depois de cada login. A shell interna pertence ao servidor tmux separado, não à sua sessão SSH. Assim, a interrupção da ligação deixa o processo CLI em execução. Volte a ligar-se, faça o attach e regressará ao mesmo histórico de saída. Se acabar por executar várias sessões de agentes no mesmo servidor, use uma sessão tmux para cada uma. Neste caso, elas não têm forma de comunicar entre si, ao contrário do Claude Code, em que uma sessão pode enviar texto para outra no mesmo VPS. Mantenha cada tarefa do Gemini independente ou coordene-as através de ficheiros no disco.

Para execuções não interativas e baseadas em scripts, o Gemini CLI tem um modo headless: gemini -p "summarise the failing tests in this repo" imprime uma resposta e termina, e --output-format json gera uma saída legível por máquinas para encaminhamento para outro processo. O modo headless com uma chave de API é precisamente o que deve usar dentro de uma sessão tmux que execute uma tarefa batch longa ou a partir de uma entrada do cron. Existe uma ressalva: uma tarefa do cron não carrega nenhum dos seus ficheiros de login. Por isso, atribua à linha do crontab o seu próprio GEMINI_API_KEY ou faça o comando carregar ~/.gemini_env. Caso contrário, o CLI recorre ao fluxo do browser e falha.

Sandboxing e permissões num servidor que também executa produção

Um agente com acesso à shell tem acesso à shell. O Gemini CLI pode executar comandos e, por predefinição, pede confirmação antes de cada comando arriscado. No entanto, é comum usar --yolo (aprovação automática de todas as chamadas de ferramentas). Nesse caso, pode apagar ficheiros, fazer push para o git ou aceder a serviços internos com toda a autoridade do utilizador com que é executado. Num servidor que também executa produção, isto representa um raio de impacto real, não um risco hipotético.

Três controlos, por ordem do benefício que proporcionam:

  • Execute-o com um utilizador dedicado e sem privilégios. Não use root nem um membro de sudo. Crie um utilizador agent com o seu próprio diretório pessoal e instale aí o Node e a CLI. Assim, uma instrução interpretada incorretamente fica confinada a essa conta. Esta é a decisão com maior impacto positivo.
  • Mantenha as credenciais de produção fora do servidor. Não disponibilize nenhum ~/.aws/credentials de produção, não copie .env da produção para o servidor e não use uma palavra-passe de base de dados com acesso de escrita a recursos importantes. Forneça uma credencial de staging ou apenas de leitura.
  • Use o sandbox integrado. Com Docker ou Podman instalado, gemini --sandbox (ou GEMINI_SANDBOX=docker) executa as chamadas de ferramentas do agente dentro de um contentor isolado do sistema de ficheiros e da rede do anfitrião. Não substitui o utilizador sem privilégios, mas é uma segunda camada forte quando o mesmo VPS executa serviços reais.

Se executar o Gemini CLI junto de outras ferramentas alojadas localmente, como um servidor MCP que expõe ferramentas ao agente no mesmo VPS, trate cada capacidade adicional como mais uma superfície a que o agente pode aceder e limite os tokens que lhe fornece exatamente a uma tarefa.

Quota, custo e o caminho de autenticação escolhido

O caminho de autenticação determina como a utilização é faturada. Uma conta Google pessoal (o caminho OAuth) utiliza o nível gratuito do Gemini Code Assist, com limites reais por minuto e por dia. Quando esses limites são excedidos, os pedidos devolvem um erro de limite de taxa até a janela ser reposta. Uma chave de API do AI Studio pode utilizar o nível gratuito ou ser faturada, consoante o projeto. Uma chave faturada aumenta os limites e cobra por token. A autenticação do Vertex e do projeto Cloud é faturada através do Google Cloud.

Há duas notas práticas. Um agente não supervisionado num ciclo pode consumir a quota rapidamente. Por isso, monitorize-o nas primeiras vezes antes de o confiar a um cron job. Se o motivo para utilizar um modelo no servidor for a privacidade ou a inferência sem medição, em vez dos modelos alojados pela Google, trata-se de outra ferramenta. alojar um LLM aberto com Ollama num VPS mantém os pesos e os pedidos no seu próprio servidor, mas implica executar um modelo muito menor do que o Gemini.

Mantê-lo atualizado

O Gemini CLI lança versões com frequência. Como foi instalado num prefixo pertencente ao utilizador, as atualizações nunca precisam de sudo:

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

Existem canais de lançamento: @latest é o estável, @preview é a versão de pré-visualização semanal e @nightly é a versão mais recente e instável. Fixe @latest em qualquer ambiente de que dependa. Com nvm, os pacotes globais ficam na versão ativa do Node. Por isso, depois de nvm use para mudar de versão do Node, pode ser necessário reinstalar a CLI. Consulte as notas de lançamento em vez de instalar todas as correções assim que ficam disponíveis.

Modos de falha, com as mensagens exatas

npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' }, seguido de uma falha da CLI durante a execução. O Node é demasiado antigo: a distribuição usa o 18.19.1, que também já ultrapassou o fim de vida. Instale o Node 20+ a partir do NodeSource ou do nvm, confirme com node --version e, se tiver vários Nodes instalados, verifique se which node aponta para o novo e não para /usr/bin/node.

npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...'. A instalação global foi feita num prefixo pertencente a root. Não use sudo; defina npm config set prefix ~/.npm-global, adicione ~/.npm-global/bin a PATH e reinstale como o seu utilizador normal. Se um sudo npm anterior tiver deixado ficheiros de cache pertencentes a root (Your cache folder contains root-owned files), execute sudo chown -R $(id -u):$(id -g) ~/.npm.

Failed to open browser, um início de sessão que fica bloqueado ou um redirect_uri=http://localhost:PORT a que não consegue aceder. O fluxo OAuth precisa de um navegador que o servidor não tem, e o callback localhost aponta para o servidor, não para o seu portátil. Use o caminho da chave da API (GEMINI_API_KEY) ou fixe OAUTH_CALLBACK_PORT, reencaminhe-o por SSH com ssh -L e abra o URL localmente.

O processo desapareceu quando a sessão SSH foi interrompida. Executou gemini diretamente na shell SSH, por isso o processo era filho dessa shell e terminou com o pty quando a ligação foi interrompida. Não há nada para recuperar. Inicie todas as sessões com tmux new -A -s gemini e execute a CLI dentro dela.

A autenticação continua a falhar com a chave definida, a CLI regressa ao seletor de autenticação ou um pedido devolve API key not valid com HTTP 400. A chave não está no ambiente que a CLI consulta. Confirme com printenv GEMINI_API_KEY; se estiver vazio, o seu ~/.gemini_env nunca foi carregado. Verifique se a linha está em ~/.bashrc, que as shells interativas (incluindo o tmux) leem, mas cron e outras shells não interativas não leem. Um espaço ou aspas indevidos dentro do valor da chave também produzem API key not valid.

429 / RESOURCE_EXHAUSTED / uma mensagem de limite de taxa. Atingiu a quota do nível de serviço usado pela sua autenticação. Aguarde até a janela ser reposta, reduza a velocidade do agente ou mude para uma chave da API faturada. Um agente preso num ciclo de novas tentativas continua a atingir este limite; pare-o e verifique o que está a fazer.

FAQ

Como autentico o Gemini CLI num servidor headless?

Use uma API key, não o login pelo browser. Crie uma key no Google AI Studio, coloque-a num ficheiro com modo 600 que a sua shell carrega (export GEMINI_API_KEY=...), e a CLI ignora completamente o fluxo OAuth pelo browser. Se quiser especificamente o free tier da conta pessoal, fixe a porta de loopback com OAUTH_CALLBACK_PORT=8085, encaminhe-a de volta para o seu laptop com ssh -L 8085:localhost:8085 user@server e abra localmente o URL apresentado. No entanto, isso exige que esteja perante um browser e não é adequado para scripts.

Por que razão a instalação global do npm pede sudo e como evito isso?

Porque o prefixo global predefinido do npm é /usr/lib/node_modules, onde o seu utilizador não pode escrever. Por isso, um npm install -g simples falha com EACCES. A solução errada é sudo npm -g, que deixa ficheiros pertencentes a root e causa falhas em instalações posteriores. A solução correta é apontar o prefixo para o seu home (npm config set prefix ~/.npm-global) e adicionar o respetivo bin a PATH, ou usar nvm, que instala automaticamente os pacotes globais no seu home.

Como mantenho o Gemini CLI em execução depois de me desligar?

Execute-o dentro do tmux. Um processo iniciado a partir da sua shell SSH termina quando a ligação cai porque é filho dessa shell. O tmux executa a shell dentro de um servidor detached que sobrevive à desligação. Use tmux new -A -s gemini, execute gemini dentro da sessão, faça detach com Ctrl-b d e volte a ligar-se mais tarde com tmux attach -t gemini.

É seguro executar o Gemini CLI num servidor de produção?

Apenas com cuidado, porque um agente com acesso à shell pode fazer tudo o que o utilizador com que é executado pode fazer. Execute-o como um utilizador dedicado sem privilégios e sem sudo, mantenha as credenciais de produção fora da máquina, evite --yolo para aprovação automática e use --sandbox (Docker ou Podman) para isolar as chamadas às ferramentas do host. A conta usada pelo processo é mais importante do que qualquer flag individual que defina.

Preciso de abrir portas na firewall para o Gemini CLI?

Não. É um cliente que faz chamadas HTTPS de saída para as APIs da Google. Precisa da porta de saída 443, mas não de portas de entrada. Se usar o túnel OAuth, a porta de callback fixa (por exemplo, 8085) fica em localhost e é alcançada através do seu encaminhamento SSH, não através de uma porta de entrada aberta. Mantenha as ligações de entrada bloqueadas.

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