Navigateur OpenClaw sur VPS : diagnostic et solution
« J’ai d’énormes problèmes avec mon VPS. Je réinstalle OpenClaw pour la 3e ou 4e fois. »
Ce message est apparu dans le Discord OpenClaw le mois dernier. L’utilisateur n’était pas le seul. Parcourez les canaux de la communauté et vous trouverez des dizaines de variantes sur le même thème : l’outil navigateur échoue, l’agent ne peut pas atteindre Chromium, le VPS n’a plus de mémoire, tout fonctionnait hier et plus rien aujourd’hui.
Si vous lisez cet article parce que vous venez de chercher « OpenClaw navigateur ne fonctionne pas VPS », vous êtes au bon endroit. Ce billet explique les cinq causes de panne, pourquoi elles interagissent de manière frustrante, et comment nous les avons toutes résolues dans l’opérateur Kubernetes d’OpenClaw.rocks pour que vous n’ayez plus jamais à vous soucier de la configuration du navigateur.
L’erreur que tout le monde voit
Le message d’erreur le plus courant dans la communauté OpenClaw est celui-ci :
Can't reach the OpenClaw browser control service
(timed out after 15000ms)
Il apparaît sur Ubuntu, Debian, dans Docker, sur Hetzner, Hostinger, GCP et partout ailleurs où l’on essaie d’utiliser OpenClaw avec l’automatisation navigateur. Les logs du gateway affichent « Browser control service ready. » Mais quand l’agent tente d’utiliser le navigateur, c’est le timeout.
L’erreur est générique. Les causes ne le sont pas. Il existe au moins cinq modes de défaillance distincts, et ils sont tous identiques vus de l’extérieur.
Défaillance 1 : Snap Chromium et le mur AppArmor
Sur un serveur Ubuntu 22.04+ fraîchement installé, which chromium-browser retourne /usr/bin/chromium-browser. Cela semble correct. Ce ne l’est pas.
Depuis Ubuntu 22.04, le paquet Chromium par défaut est un snap. Lorsque le gateway d’OpenClaw tente de lancer ce binaire via un service systemd, la couche de confinement AppArmor le bloque. Le paquet snap ne peut pas ouvrir les ports de débogage Chrome DevTools Protocol (CDP) à travers la sandbox. Le binaire se lance, semble démarrer, puis échoue silencieusement à ouvrir le port dont OpenClaw a besoin.
Vous verrez « Failed to start Chrome CDP on port 18800 » dans les logs, ou parfois rien du tout. Le processus du navigateur démarre et meurt avant d’écrire une seule ligne de log.
La solution est d’installer le paquet .deb de Google Chrome ou d’utiliser le binaire Chromium autonome de Playwright depuis ~/.cache/ms-playwright/. Les deux contournent la sandbox snap. Mais la solution n’est pas évidente. La détection de navigateur d’OpenClaw parcourt les chemins standard dans l’ordre, trouve le binaire snap en premier et tente de l’utiliser. L’issue GitHub #4978 contient une description complète.
Défaillance 2 : Des paramètres headless qui supposent un affichage
OpenClaw est livré avec headless: false et noSandbox: false comme paramètres par défaut du navigateur. C’est logique sur un Mac ou un PC Windows avec un écran. Sur un VPS, il n’y a pas d’écran. Sans configuration explicite, Chromium tente d’ouvrir une fenêtre sur un serveur d’affichage qui n’existe pas.
Deux modifications de configuration règlent le problème :
openclaw config set browser.headless true
openclaw config set browser.noSandbox true
La plupart des guides VPS le mentionnent. Mais si vous suivez les instructions d’installation standard d’OpenClaw, aucune de ces deux lignes n’apparaît. Vous installez, vous testez le navigateur, il échoue. Vous cherchez l’erreur. Vous trouvez un billet de blog. Vous ajoutez la configuration. Vous redémarrez. Et vous passez à la défaillance numéro trois.
Défaillance 3 : Le OOM kill invisible
Un seul onglet Chromium avec quelques pages ouvertes consomme 2 à 4 Go de RAM. Sur un VPS de 4 Go, il ne reste presque rien pour OpenClaw lui-même, le système d’exploitation et les autres services en cours d’exécution.
Quand Linux manque de mémoire, le OOM killer du noyau termine le processus le plus gourmand. C’est Chromium. Le processus meurt. OpenClaw enregistre un timeout navigateur. Pas de rapport de crash, pas de stack trace, aucune indication que la mémoire était en cause.
Il existe aussi une version plus subtile de ce problème. Chromium lance des processus de rendu enfants pour chaque onglet. Si ces processus ne sont pas correctement nettoyés, ils s’accumulent. Une issue GitHub a documenté 39 processus de rendu orphelins consommant 3,8 Go de RAM sur un VPS censé avoir largement assez de marge.
Vous pouvez vérifier après coup avec dmesg | grep -i "oom\|killed\|chromium", mais la plupart des gens ne pensent pas à regarder là. Ils redémarrent OpenClaw, ça fonctionne quelques minutes, puis ça recommence.
La page officielle des prérequis serveur recommande 4 Go minimum pour une installation de base. Mais ce chiffre suppose l’absence d’automatisation navigateur. Avec le navigateur activé, 8 Go est le plancher réaliste. Chez Hetzner, c’est la différence entre un cpx22 (5 $/mois) et un cpx42 (17 $/mois).
Défaillance 4 : La mémoire partagée manquante de Docker
Si vous exécutez OpenClaw dans Docker (courant pour les déploiements VPS), un autre piège vous attend. Le /dev/shm par défaut de Docker est de 64 Mo. Chromium utilise la mémoire partagée pour la communication inter-processus. Quand elle est épuisée, les onglets crashent silencieusement ou affichent des pages blanches.
La solution tient en une ligne dans votre docker-compose.yml :
shm_size: '2gb'
Ou montez-la explicitement :
volumes:
- /dev/shm:/dev/shm
Ce n’est pas documenté dans le guide d’installation d’OpenClaw. C’est un comportement spécifique à Docker qui affecte toute application utilisant Chromium, mais si vous n’avez jamais déployé de navigateurs headless dans Docker, vous ne savez pas qu’il faut chercher ça.
Défaillance 5 : Les collisions de ports dont personne ne vous prévient
Le service de contrôle navigateur d’OpenClaw tourne sur un port séparé du gateway. Par défaut, c’est le port du gateway plus 2. Si votre gateway est sur 18789, le service de contrôle navigateur devrait être sur 18791, et le relais d’extension sur 18792.
Dans Docker, si vous n’exposez que le port 18789, le service de contrôle navigateur est inaccessible depuis l’extérieur du conteneur. Pire encore, le gateway enregistre « Browser control service ready » même quand le port 18791 ne se lie jamais réellement. L’issue #17584 a retracé le problème jusqu’au gateway qui importait le mauvais module : un module qui enregistre le message « ready » sans démarrer le serveur HTTP. Le log vous dit que tout va bien. Le port est mort.
Dans Kubernetes, si un autre conteneur dans le même pod utilise déjà le port 9222 (le port CDP standard), la fonction ensurePortAvailable() d’OpenClaw détecte le port comme occupé et refuse de se connecter, même si l’occupant est exactement l’instance Chromium avec laquelle OpenClaw devrait communiquer.
L’issue GitHub #10994 documente un cas où le setup VPS de l’utilisateur fonctionnait correctement. Puis, après quelques actions automatisées, le port CDP s’est bloqué. La seule solution était de trouver et tuer les processus Chromium parasites qui bloquaient le port.
Pourquoi ces défaillances s’accumulent
Chacun de ces cinq problèmes a une solution connue. Mais ils interagissent. Vous résolvez le problème snap et vous tombez sur le paramètre headless par défaut. Vous corrigez la configuration et Chromium démarre. Il tourne dix minutes, puis le OOM killer le supprime. Vous ajoutez de l’espace swap, et maintenant la limite de mémoire partagée de Docker provoque des erreurs de rendu silencieuses. Vous corrigez ça et découvrez que le port 18791 n’est pas exposé.
La boucle de débogage ressemble à ceci : chercher l’erreur, trouver un correctif partiel, appliquer le correctif, tomber sur l’erreur suivante, recommencer. Un utilisateur Discord a décrit avoir réinstallé son OS entier « pour la 3e ou 4e fois ». Un autre a signalé que le navigateur était « instable » après ce qu’il pensait être une installation complète. Un troisième a ouvert une issue intitulée simplement « Browser tool consistently fails on VPS ».
Le problème n’est pas que chaque correctif individuel soit difficile. Le problème est qu’il y en a cinq, qu’ils dépendent de votre OS, gestionnaire de paquets, runtime de conteneurs et fournisseur VPS spécifiques, et qu’une seule erreur dans la chaîne signifie que le navigateur ne fonctionne pas.
Il faut reconnaître que l’équipe OpenClaw corrige régulièrement les bugs associés. Le log « ready » trompeur, le nettoyage des renderers orphelins et la gestion du port CDP se sont tous améliorés dans les versions récentes. Mais les correctifs en amont traitent les symptômes dans le code d’OpenClaw. Ils ne peuvent pas installer le bon binaire Chromium sur votre serveur, configurer la mémoire partagée Docker ou allouer assez de RAM pour l’automatisation navigateur. Ça reste votre responsabilité.
Comment nous avons cassé Chromium trois fois (et ce que nous en avons appris)
Nous exécutons chaque agent OpenClaw.rocks sur Kubernetes avec notre opérateur open source. Le sidecar navigateur nous a pris des semaines à faire fonctionner correctement. Nous avons rencontré notre propre version de chaque problème décrit ci-dessus, plus quelques-uns qui n’apparaissent que dans un contexte d’orchestration de conteneurs.
L’idée était simple : exécuter Chromium comme conteneur séparé à côté d’OpenClaw, connecté via CDP. Une ligne dans la Custom Resource et le navigateur fonctionne, tout simplement.
spec:
chromium:
enabled: true
Voici comment cette unique ligne est réellement née.
Crash 1 : Mauvais utilisateur, système de fichiers en lecture seule
Notre premier essai exécutait le conteneur Chromium en UID 1001 avec un système de fichiers racine en lecture seule. Bonne pratique de sécurité. Et complètement cassé. L’image browserless attend l’UID 999 (blessuser), et Node.js appelle os.userInfo() au démarrage, ce qui échoue avec ENOENT quand l’UID n’a pas d’entrée /etc/passwd. Même après avoir corrigé l’UID, le système de fichiers en lecture seule empêchait Chrome d’écrire des fichiers temporaires. Le sidecar crashait à chaque démarrage avant d’écrire une seule ligne de log. L’issue #12 raconte toute l’histoire.
Crash 2 : Le mur de sécurité WebSocket
Avec le conteneur enfin en marche, Chromium tournait, CDP répondait sur le port 9222, mais OpenClaw refusait de l’utiliser. Le gateway se liait à l’IP LAN du pod (nécessaire pour le routage Kubernetes Service), et la couche de sécurité d’OpenClaw bloquait les connexions ws:// en clair vers des adresses non-loopback : « SECURITY ERROR: Gateway URL uses plaintext ws:// to a non-loopback address. Both credentials and chat data would be exposed to network interception. »
Une vérification de sécurité légitime. Mais dans un pod Kubernetes, tous les conteneurs partagent un namespace réseau. Le trafic entre eux ne quitte jamais le noeud. Nous ne pouvions pas modifier la vérification de sécurité d’OpenClaw, alors nous avons ajouté un sidecar reverse proxy nginx qui écoute sur toutes les interfaces et transfère vers le gateway sur loopback. Le gateway reste sécurisé. Le Service reste accessible. L’issue #135 documente le débogage.
Crash 3 : Collision sur le port 3000
Chromium tournait. Le gateway était proxifié. Mais le navigateur ne se connectait toujours pas. L’image browserless utilise le port 3000 par défaut, ce qui entrait en collision avec le service de contrôle navigateur interne d’OpenClaw. Et quand nous sommes passés au port 9222, la fonction ensurePortAvailable() d’OpenClaw l’a détecté comme « utilisé par autre chose » et a refusé la connexion, car dans un namespace réseau partagé, le port du sidecar a l’air local.
La solution a été d’utiliser l’adresse IP du pod (via la Kubernetes Downward API) au lieu de localhost pour l’URL CDP. Une adresse non-loopback indique à OpenClaw d’utiliser le mode remote/attach-only : se connecter à ce qui tourne déjà au lieu de tenter de lancer son propre navigateur. La PR #183 a résolu ce problème.
Le résultat : cinq correctifs, appliqués automatiquement
Chacun de ces crashes nous a appris quelque chose. L’opérateur actuel encode tout ce savoir :
Isolation par sidecar. Chromium tourne dans son propre conteneur. Pas de snap. Pas de Playwright. Pas de flags headless. L’image browserless gère tout cela.
Ressources dédiées. Le sidecar a ses propres limites CPU et mémoire (250m-1000m CPU, 512Mi-2Gi RAM par défaut, configurable). Si Chromium dépasse sa limite mémoire, Kubernetes ne redémarre que le conteneur navigateur. Votre agent continue de tourner.
Mémoire partagée. L’opérateur monte automatiquement un volume de 1 Go en mémoire à /dev/shm. Pas besoin de configuration shm_size Docker.
Routage des ports. L’IP du pod pour l’URL CDP active le mode distant. OpenClaw se connecte au sidecar au lieu d’essayer de revendiquer le port. Le conflit ensurePortAvailable() disparaît.
Détection anti-bot intégrée. De nombreux sites web détectent le Chromium headless par défaut et bloquent l’automatisation. L’opérateur prend en charge les extraArgs sur le sidecar Chromium. Vous pouvez ainsi passer des flags comme --disable-blink-features=AutomationControlled et des user-agents personnalisés sans construire une image conteneur personnalisée :
spec:
chromium:
enabled: true
extraArgs:
- "--disable-blink-features=AutomationControlled"
- "--user-agent=Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
- "--window-size=1920,1080"
Sécurité sans compromis. Toutes les capacités Linux supprimées, escalade de privilèges désactivée, seccomp RuntimeDefault, UID 999 non-root. Pas de --no-sandbox en root.
Ce que cela signifie pour vous
Si vous utilisez OpenClaw sur un VPS et que le navigateur fonctionne, félicitations. Vous avez navigué à travers cinq modes de défaillance distincts et vous en êtes sorti. Gardez votre setup. Sauvegardez votre configuration.
Si le navigateur ne fonctionne pas, ou s’il fonctionne par intermittence, ou si vous en avez assez de déboguer Chromium sur un VPS à 5 dollars, réfléchissez à ce que vaut votre temps.
OpenClaw.rocks exécute chaque agent sur Kubernetes avec l’opérateur décrit ci-dessus. Le sidecar navigateur est préconfiguré. La mémoire est allouée. Les ports sont routés. La sécurité est renforcée. Vous n’installez rien, ne configurez rien et ne déboguez rien.
Votre agent obtient un navigateur qui fonctionne. À chaque fois. Prêt à l’emploi.
Les cinq correctifs en résumé
Si vous souhaitez rester en auto-hébergement, voici la checklist complète :
- Remplacer Chromium snap par le
.debGoogle Chrome ou le binaire autonome de Playwright - Activer le mode headless :
openclaw config set browser.headless trueetbrowser.noSandbox true - Allouer 8 Go+ de RAM ou ajouter 4 Go de swap pour l’automatisation navigateur
- Monter la mémoire partagée dans Docker :
shm_size: '2gb' - Exposer les trois ports : gateway, contrôle navigateur (gateway + 2) et relais d’extension (gateway + 3)
Ou passez la checklist. Obtenez votre assistant sur OpenClaw.rocks et laissez-nous gérer l’infrastructure.