SSD Nodes Learn Hosting plans →
Guides Matt ConnorPar Matt Connor · Mis à jour le 2026-08-22

Installer Gemini CLI sur un VPS sans interface graphique

Installez Gemini CLI sur un VPS sans navigateur : Node récent, npm global sans sudo, clé API sans historique shell et tmux pour survivre aux coupures SSH.

Ce que vous allez mettre en place

Un Gemini CLI toujours actif sur un serveur qui vous appartient, accessible en SSH, et capable d’exécuter de longues tâches d’agent qui continuent après la fermeture de votre ordinateur portable. L’installation se fait en trois commandes. Le travail consiste surtout à gérer tout ce qui suppose l’utilisation d’un ordinateur de bureau : le CLI de Google veut ouvrir un navigateur pour vous connecter, mais votre serveur n’en possède pas. Ce guide suit donc principalement la méthode headless, l’installation d’une version récente de Node que la distribution ne fournit pas, l’installation globale de npm sans utiliser root, l’authentification sans navigateur avec une clé API qui ne s’affiche pas dans l’historique du shell, ainsi que tmux pour qu’une session SSH interrompue n’arrête pas une tâche en cours.

Gemini CLI est un programme Node open source (Apache-2.0) (@google/gemini-cli) qui communique avec les modèles Gemini de Google et peut lire et écrire des fichiers, exécuter des commandes shell et utiliser des outils dans le répertoire de travail. Sur un VPS, il s’agit d’un agent léger et toujours disponible que vous pouvez laisser travailler. C’est pourquoi le compte sous lequel il s’exécute et les identifiants stockés sur le serveur sont plus importants que n’importe quel réglage présenté ici.

Prérequis et pièges à connaître

  • Un VPS KVM Ubuntu 24.04 neuf avec root ou sudo. Tous les forfaits KVM conviennent ; l’interface CLI est légère et consomme quelques centaines de Mo de RAM au repos.
  • Node.js 20 ou une version ultérieure. C’est la seule version minimale stricte. Le paquet de la distribution est trop ancien ; consultez la section suivante.
  • Un accès HTTPS sortant (port 443) vers les API de Google. Aucun port entrant n’est nécessaire : il s’agit d’un client, pas d’un serveur. Vous n’avez donc pas besoin d’ouvrir de règle de pare-feu.
  • Un moyen de vous authentifier sans navigateur sur le serveur : soit une clé d’API Gemini obtenue dans Google AI Studio, soit un tunnel SSH vers un navigateur sur votre propre machine. La méthode avec clé d’API est celle qui convient aux scripts et aux exécutions sans intervention.
  • Docker ou Podman, uniquement si vous voulez l’isolation --sandbox. C’est facultatif ; cette option est présentée vers la fin.

Le piège qui concerne tout le monde : le parcours de connexion initial convivial de gemini est conçu pour un ordinateur de bureau. Il tente d’ouvrir un navigateur et, sur une machine headless, échoue ou vous fournit un lien qui ne fonctionne pas. Choisissez la méthode d’authentification avant de commencer.

Node : le paquet de la distribution est trop ancien

Ubuntu 24.04 fournit Node 18.19.1 dans ses propres dépôts, avec npm 9.2.0. Le package.json de Gemini CLI déclare engines: { node: ">=20" }. Par défaut, npm ne bloque pas strictement une incompatibilité de version : il installe quand même le paquet et affiche un avertissement qui indique l’écart :

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 }

Si vous ignorez cet avertissement, le CLI s’exécute avec un runtime non pris en charge. Il peut alors fonctionner de manière incorrecte ou planter dès qu’il utilise une API de Node 20+ qu’il s’attend à trouver. Node 18 est également arrivé en fin de vie en avril 2025. Dans tous les cas, cette version ne convient pas. Installez une version LTS actuelle avant d’installer le CLI. Deux méthodes sont adaptées : NodeSource, un dépôt apt signé disponible à l’échelle du système, ou nvm, un gestionnaire de versions par utilisateur. Choisissez-en une.

NodeSource, si vous voulez rendre Node disponible pour tous les utilisateurs du serveur :

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 doit afficher v20.x ou une version ultérieure. v24.x est la version LTS actuellement active. Consultez la page de NodeSource pour connaître le script d’installation actuel. Le setup_24.x dans l’URL correspond à la valeur à modifier lorsqu’une nouvelle version LTS est publiée.

nvm, si vous préférez conserver Node dans le répertoire personnel d’un seul utilisateur et ne jamais l’utiliser avec sudo :

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

Le v0.40.1 présent dans cette URL était actuel au moment de la rédaction. Consultez le README de nvm pour connaître la dernière version et remplacez la version dans l’URL avant d’exécuter la commande. nvm présente un avantage important dans ce cas : il installe Node et ses paquets globaux sous ~/.nvm. Le problème de permissions lors d’une installation globale, présenté dans la section suivante, ne se produit donc pas. Si vous choisissez nvm, vous pouvez ignorer l’étape de configuration du préfixe npm.

Installer la CLI sans sudo npm -g

La commande tentante est sudo npm install -g @google/gemini-cli. Ne l’utilisez pas. Un prefix global appartenant à root provoque des erreurs de permissions lors de toutes les installations suivantes et laisse des fichiers appartenant à root dans votre cache npm, ce qui peut poser problème des mois plus tard. Exécutez un npm install -g simple, sans sudo, avec un Node système, et vous obtenez l’autre erreur :

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 essaie alors d’écrire dans /usr/lib, ce que votre utilisateur ne peut pas faire. La solution n’est pas sudo. Il faut définir le prefix global de npm dans votre répertoire personnel, afin que les installations globales soient placées à un emplacement dont vous êtes propriétaire :

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, et non ~/.profile, est volontaire : tmux, dans lequel vous exécuterez la CLI deux sections plus loin, démarre un shell non-login qui lit ~/.bashrc et ignore ~/.profile. Une ligne PATH placée dans le mauvais fichier rend donc gemini invisible exactement à l’endroit où vous en avez besoin. Il suffit que gemini --version affiche un numéro de version pour valider le test. Si vous obtenez plutôt gemini: command not found, l’export PATH n’a pas été appliqué ; consultez les modes d’échec. Avec nvm, ignorez entièrement les lignes de prefix : nvm installe déjà les paquets globaux dans votre répertoire personnel.

Si vous avez exécuté sudo npm auparavant et que vous voyez maintenant Your cache folder contains root-owned files, corrigez le problème une fois avec sudo chown -R $(id -u):$(id -g) ~/.npm.

Le problème d’authentification sans interface graphique et comment le résoudre

Exécutez gemini en mode interactif pour la première fois. La commande vous propose alors de vous connecter avec votre compte Google. Sur un poste de travail, un onglet de navigateur s’ouvre. Sur un VPS headless, aucun navigateur n’est disponible. Le processus affiche donc une URL localhost qu’il vous demande d’ouvrir, ou échoue directement avec un message similaire à celui-ci :

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

Le problème vient de redirect_uri=http://localhost:PORT. Même si vous ouvrez cette URL sur votre ordinateur portable et validez la connexion, Google redirige vers http://localhost:PORT, c’est-à-dire vers localhost sur le serveur. Aucun service de votre ordinateur portable ne peut atteindre ce port. La connexion n’aboutit jamais.

Deux solutions permettent de résoudre correctement le problème.

La première consiste à utiliser une clé d’API. C’est le choix recommandé par défaut sur un serveur. Créez une clé dans Google AI Studio (aistudio.google.com), puis transmettez-la à la CLI avec une variable d’environnement. La CLI lit GEMINI_API_KEY et ignore entièrement le processus d’authentification dans le navigateur. Reste à éviter de conserver la clé dans l’historique ou dans des fichiers lisibles par tous. Ne saisissez pas export GEMINI_API_KEY=AIza... à l’invite : la valeur serait enregistrée en clair dans ~/.bash_history. Ne la placez pas non plus dans un fichier accessible aux autres utilisateurs. Écrivez-la dans un fichier avec le mode 600, que le shell charge au démarrage :

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 signifie que seul votre utilisateur peut lire le fichier. Vérifiez que la clé est bien présente dans l’environnement avec printenv GEMINI_API_KEY. Si cette commande n’affiche rien, la CLI revient au processus d’authentification dans le navigateur et échoue. La CLI lit également un fichier .env dans ~/.gemini/ si vous préférez cette organisation. La même règle s’applique : chmod 600 ~/.gemini/.env.

La seconde solution conserve la connexion avec un compte Google personnel, ainsi que son offre gratuite, en redirigeant le callback OAuth vers votre ordinateur portable à travers un tunnel SSH. Le problème est que le serveur loopback de la CLI utilise un port aléatoire à chaque exécution. Aucun port stable ne peut donc être redirigé, sauf si vous le fixez d’abord avec la variable d’environnement OAUTH_CALLBACK_PORT, puis redirigez exactement ce 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

La CLI ne peut pas ouvrir de navigateur. Elle affiche donc l’URL d’authentification. Ouvrez cette URL dans le navigateur de votre ordinateur portable, validez la connexion, puis Google redirige vers http://localhost:8085/.... La redirection SSH transmet alors la requête au serveur loopback du VPS et la connexion aboutit. Si vous ne fixez pas le port, un nouveau port aléatoire est utilisé à chaque exécution. Aucun ssh -L configuré à l’avance ne peut alors le prendre en charge. Cette méthode fonctionne, mais elle nécessite un navigateur ouvert par un utilisateur. Elle ne convient donc pas aux scripts. Pour tout processus exécuté en continu, utilisez la clé d’API.

Pour utiliser Vertex AI ou un projet Google Cloud à la place d’AI Studio, définissez GOOGLE_API_KEY avec GOOGLE_GENAI_USE_VERTEXAI=true, ou GOOGLE_CLOUD_PROJECT pour une licence Code Assist. Appliquez les mêmes règles aux variables d’environnement et utilisez le même fichier avec le mode 600.

Lancez-le dans tmux pour qu’une déconnexion SSH ne l’arrête pas

Un processus gemini lancé directement depuis votre shell SSH est un enfant de ce shell. Si la connexion est interrompue, que l’ordinateur portable est fermé, que le Wi-Fi se coupe ou qu’un délai d’inactivité est atteint, sshd détruit le pseudo-terminal, le shell reçoit SIGHUP et le transmet à son tour à la CLI. Une tâche qui modifie des fichiers depuis dix minutes s’arrête avec lui. À la reconnexion, vous ne pouvez récupérer aucun processus.

tmux corrige ce problème en prenant possession du shell, au lieu de laisser sshd le contrôler. C’est le même principe que pour lancer un agent de codage IA sur un VPS distant dans tmux, et cela fonctionne de la même manière ici :

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 se connecte à une session nommée gemini si elle existe, et la crée sinon. C’est donc la commande à exécuter juste après chaque connexion. Le shell appartient au serveur tmux détaché, et non à votre session SSH. Une déconnexion laisse donc la CLI fonctionner. Reconnectez-vous, rattachez la session et vous retrouvez le même historique de défilement. Si vous exécutez plusieurs sessions d’agents sur une même machine, utilisez une session tmux par agent. Dans ce contexte, elles ne peuvent pas communiquer entre elles, contrairement à Claude Code, où une session peut transmettre du texte à une autre sur le même VPS. Gardez donc chaque tâche Gemini indépendante ou coordonnez-les avec des fichiers sur le disque.

Pour les exécutions scriptées non interactives, Gemini CLI propose un mode headless : gemini -p "summarise the failing tests in this repo" affiche une réponse puis se termine, et --output-format json produit une sortie lisible par une machine, que vous pouvez transmettre à une autre commande. Avec une clé API, le mode headless convient exactement à une session tmux qui exécute un long traitement par lots, ou à une commande lancée par cron. Il y a toutefois une particularité : une tâche cron ne source aucun de vos fichiers de connexion. Donnez donc à la ligne crontab son propre GEMINI_API_KEY, ou faites sourcer ~/.gemini_env par la commande. Sinon, la CLI revient au parcours via le navigateur et échoue.

Isolation et permissions sur un serveur qui héberge aussi de la production

Un agent qui dispose d’un accès shell dispose d’un shell. Gemini CLI peut exécuter des commandes et demande par défaut une confirmation avant chaque commande risquée. Mais il est tentant d’utiliser --yolo (validation automatique de chaque appel d’outil). L’agent peut alors supprimer des fichiers, pousser des modifications vers Git ou accéder à des services internes avec tous les droits de l’utilisateur qui l’exécute. Sur un serveur qui héberge aussi de la production, le périmètre d’impact est réel, et non théorique.

Trois contrôles, classés selon leur efficacité :

  • Exécutez-le avec un utilisateur dédié et sans privilèges. Ni root ni membre de sudo. Créez un utilisateur agent avec son propre répertoire personnel, puis installez-y Node et la CLI. Une instruction mal interprétée reste ainsi limitée à ce compte. C’est la décision qui apporte le plus de sécurité.
  • Ne stockez pas les identifiants de production sur le serveur. Pas de ~/.aws/credentials de production, pas de .env copié depuis la production, et aucun mot de passe de base de données disposant de droits d’écriture sur une ressource importante. Utilisez un identifiant de staging ou en lecture seule.
  • Utilisez le sandbox intégré. Si Docker ou Podman est installé, gemini --sandbox (ou GEMINI_SANDBOX=docker) exécute les appels d’outils de l’agent dans un conteneur isolé du système de fichiers et du réseau de l’hôte. Cela ne remplace pas l’utilisateur sans privilèges, mais constitue une seconde couche efficace lorsque le même VPS exécute de vrais services.

Si vous exécutez Gemini CLI à côté d’autres outils auto-hébergés, par exemple un serveur MCP qui expose des outils à l’agent sur le même VPS, considérez chaque nouvelle fonctionnalité comme une surface supplémentaire accessible à l’agent. Limitez les jetons qui lui sont transmis à une seule tâche précise.

Quota, coût et méthode d’authentification choisie

La méthode d’authentification détermine votre facturation. Un compte Google personnel (la méthode OAuth) utilise l’offre gratuite de Gemini Code Assist, avec de véritables limites par minute et par jour. Si vous les dépassez, les requêtes renvoient une erreur de limitation de débit jusqu’à la réinitialisation de la fenêtre. Une clé API créée dans AI Studio peut relever de l’offre gratuite ou être facturée selon le projet. Une clé associée à la facturation augmente les limites et facture les tokens utilisés. L’authentification avec Vertex et un projet Cloud est facturée via Google Cloud.

Deux remarques pratiques. Un agent unattended exécuté en boucle peut épuiser rapidement le quota. Surveillez-le donc les premières fois avant de le confier à une tâche cron. Si vous utilisez un modèle côté serveur pour des raisons de confidentialité ou pour obtenir une inférence sans quota, plutôt que les modèles hébergés par Google, il s’agit d’un autre outil. Héberger vous-même un LLM open source avec Ollama sur un VPS conserve les poids du modèle et les prompts sur votre propre serveur, au prix de l’utilisation d’un modèle beaucoup plus petit que Gemini.

Maintenir l’outil à jour

Gemini CLI publie fréquemment de nouvelles versions. Comme vous l’avez installé dans un préfixe appartenant à votre utilisateur, les mises à jour ne nécessitent jamais sudo :

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

Il existe plusieurs canaux de publication : @latest est le canal stable, @preview est l’aperçu hebdomadaire et @nightly est le canal de développement le plus avancé. Épinglez la version sur @latest pour tout ce dont vous dépendez. Avec nvm, les paquets globaux sont installés sous la version active de Node. Après nvm use pour changer de version de Node, vous devrez peut-être réinstaller la CLI. Consultez les notes de version au lieu d’installer chaque correctif dès sa publication.

Modes de défaillance, avec les chaînes exactes

npm WARN EBADENGINE Unsupported engine ... required: { node: '>=20' }, puis l’interface CLI plante à l’exécution. Node est trop ancien : la distribution fournit la version 18.19.1, qui n’est plus supportée. Installez Node 20+ avec NodeSource ou nvm, vérifiez la version avec node --version et, si plusieurs versions de Node sont installées, vérifiez que which node pointe vers la nouvelle version et non vers /usr/bin/node.

npm error code EACCES / permission denied, mkdir '/usr/lib/node_modules/...'. L’installation globale utilise un préfixe appartenant à root. N’utilisez pas sudo, définissez npm config set prefix ~/.npm-global, ajoutez ~/.npm-global/bin à PATH, puis réinstallez en tant qu’utilisateur normal. Si un précédent sudo npm a créé des fichiers de cache appartenant à root (Your cache folder contains root-owned files), exécutez sudo chown -R $(id -u):$(id -g) ~/.npm.

Failed to open browser, une connexion qui reste bloquée ou un redirect_uri=http://localhost:PORT inaccessible. Le flux OAuth attend un navigateur que le serveur ne possède pas, et son callback localhost pointe vers le serveur, pas vers votre ordinateur portable. Utilisez la méthode avec clé d’API (GEMINI_API_KEY) ou forcez OAUTH_CALLBACK_PORT, transférez-le avec SSH à l’aide de ssh -L, puis ouvrez l’URL localement.

Le processus a disparu lorsque la connexion SSH s’est interrompue. Vous avez lancé gemini directement depuis le shell SSH. Le processus était donc un enfant de ce shell et s’est arrêté avec le pty lors de la déconnexion. Il n’y a rien à récupérer. Commencez chaque session avec tmux new -A -s gemini et exécutez la CLI à l’intérieur.

L’authentification échoue toujours alors que la clé est définie, la CLI revient à son sélecteur d’authentification ou une requête renvoie API key not valid avec HTTP 400. La clé n’est pas présente dans l’environnement visible par la CLI. Vérifiez avec printenv GEMINI_API_KEY. Si le résultat est vide, votre ~/.gemini_env n’a jamais été chargé. Vérifiez que la ligne se trouve dans ~/.bashrc, que les shells interactifs, y compris tmux, lisent, contrairement à cron et aux autres shells non interactifs. Un espace ou un guillemet superflu dans la valeur de la clé produit également API key not valid.

429 / RESOURCE_EXHAUSTED / un message de limite de débit. Vous avez atteint le quota du niveau utilisé par votre authentification. Attendez la réinitialisation de la fenêtre, ralentissez l’agent ou utilisez une clé d’API facturée. Un agent bloqué dans une boucle de nouvelles tentatives continue d’atteindre cette limite. Arrêtez-le et vérifiez ce qu’il fait.

FAQ

Comment authentifier Gemini CLI sur un serveur sans interface graphique ?

Utilisez une clé d’API, pas la connexion au navigateur. Créez une clé dans Google AI Studio, placez-la dans un fichier avec les permissions 600 que votre shell charge (export GEMINI_API_KEY=...), et le CLI ignore entièrement le flux OAuth dans le navigateur. Si vous voulez précisément bénéficier de l’offre gratuite avec un compte personnel, fixez le port loopback avec OAUTH_CALLBACK_PORT=8085, transférez-le vers votre ordinateur portable avec ssh -L 8085:localhost:8085 user@server, puis ouvrez localement l’URL affichée. Cette méthode nécessite toutefois votre présence devant un navigateur. Elle ne convient donc pas aux scripts.

Pourquoi l’installation globale avec npm demande-t-elle sudo, et comment l’éviter ?

Parce que le préfixe global par défaut de npm est /usr/lib/node_modules, dans lequel votre utilisateur ne peut pas écrire. Une simple commande npm install -g échoue donc avec EACCES. La mauvaise solution consiste à utiliser sudo npm -g. Elle crée des fichiers appartenant à root, ce qui fait échouer les installations suivantes. La bonne solution consiste à définir le préfixe dans votre répertoire personnel (npm config set prefix ~/.npm-global) et à ajouter son chemin bin à PATH, ou à utiliser nvm, qui installe automatiquement les paquets globaux dans votre répertoire personnel.

Comment laisser Gemini CLI s’exécuter après ma déconnexion ?

Exécutez-le dans tmux. Un processus démarré depuis votre shell SSH s’arrête lorsque la connexion est interrompue, car il est enfant de ce shell. tmux exécute le shell dans un serveur détaché qui continue de fonctionner après la déconnexion. Utilisez tmux new -A -s gemini, exécutez gemini à l’intérieur, détachez-vous avec Ctrl-b d, puis rattachez-vous plus tard avec tmux attach -t gemini.

Est-il sûr d’exécuter Gemini CLI sur un serveur de production ?

Oui, mais uniquement avec prudence, car un agent ayant accès au shell peut effectuer toutes les opérations autorisées à l’utilisateur sous lequel il s’exécute. Exécutez-le avec un utilisateur dédié et non privilégié, sans sudo. Ne stockez pas les identifiants de production sur la machine. Évitez l’approbation automatique avec --yolo et utilisez --sandbox (Docker ou Podman) pour isoler les appels aux outils du système hôte. Le compte utilisé par l’agent compte davantage que n’importe quel indicateur individuel.

Dois-je ouvrir des ports du pare-feu pour Gemini CLI ?

Non. Il s’agit d’un client qui établit des connexions HTTPS sortantes vers les API Google. Il a donc besoin du port sortant 443, mais d’aucun port entrant. Si vous utilisez le tunnel OAuth, le port de callback fixé (par exemple 8085) reste lié à localhost et est accessible via votre tunnel SSH, pas par un port entrant ouvert. Gardez les connexions entrantes bloquées.

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