“Heb enorme problemen met mijn VPS. Ik installeer OpenClaw nu voor de 3e of 4e keer opnieuw.”

Dit bericht verscheen vorige maand in de OpenClaw Discord. De gebruiker was niet de enige. Scroll door de communitykanalen en u vindt tientallen variaties op hetzelfde thema: de browsertool faalt, de agent kan Chromium niet bereiken, het VPS heeft geen geheugen meer, gisteren werkte alles en nu niet meer.

Als u dit leest omdat u zojuist “OpenClaw browser werkt niet VPS” heeft gezocht, bent u hier aan het juiste adres. Dit artikel legt de vijf dingen uit die misgaan, waarom ze op frustrerende wijze op elkaar inwerken, en hoe we ze allemaal hebben opgelost in de OpenClaw.rocks Kubernetes operator zodat u zich nooit meer druk hoeft te maken over browserconfiguratie.

De foutmelding die iedereen ziet

De meest voorkomende foutmelding in de OpenClaw-community is deze:

Can't reach the OpenClaw browser control service
(timed out after 15000ms)

Hij verschijnt op Ubuntu, Debian, in Docker, op Hetzner, Hostinger, GCP en overal waar mensen OpenClaw met browserautomatisering proberen te draaien. De gateway-logs melden “Browser control service ready.” Maar wanneer de agent de browser probeert te gebruiken, treedt er een timeout op.

De fout is generiek. De oorzaken niet. Er zijn minstens vijf verschillende faalwijzen, en ze zien er van buitenaf allemaal identiek uit.

Fout 1: Snap Chromium en de AppArmor-muur

Op een verse Ubuntu 22.04+ server geeft which chromium-browser het pad /usr/bin/chromium-browser terug. Dat ziet er correct uit. Dat is het niet.

Sinds Ubuntu 22.04 is het standaard Chromium-pakket een snap. Wanneer het gateway van OpenClaw dat binary probeert te starten via een systemd-service, blokkeert de confinement-laag van AppArmor het. Het snap-pakket kan geen Chrome DevTools Protocol (CDP) debugging-poorten openen door de sandbox. Het binary start op, lijkt te draaien, en faalt vervolgens stilletjes bij het openen van de poort die OpenClaw nodig heeft.

U ziet “Failed to start Chrome CDP on port 18800” in de logs, of soms helemaal niets. Het browserproces start en sterft voordat het een enkele logregel schrijft.

De oplossing is het installeren van het .deb-pakket van Google Chrome of het gebruik van het standalone Chromium-binary van Playwright uit ~/.cache/ms-playwright/. Beide omzeilen de snap-sandbox. Maar de oplossing is niet voor de hand liggend. De browserdetectie van OpenClaw scant standaardpaden op volgorde, vindt eerst het snap-binary en probeert dat te gebruiken. GitHub issue #4978 bevat een volledige beschrijving.

Fout 2: Headless-standaardwaarden die een beeldscherm veronderstellen

OpenClaw wordt geleverd met headless: false en noSandbox: false als browserstandaarden. Dit is logisch op een Mac of Windows-machine met een beeldscherm. Op een VPS is er geen beeldscherm. Zonder expliciete configuratie probeert Chromium een venster te openen op een displayserver die niet bestaat.

Twee configuratiewijzigingen lossen het op:

openclaw config set browser.headless true
openclaw config set browser.noSandbox true

De meeste VPS-handleidingen vermelden dit. Maar als u de standaard OpenClaw-installatie-instructies volgt, verschijnt geen van beide regels. U installeert, probeert de browser, het faalt. U zoekt de fout. U vindt een blogartikel. U past de configuratie aan. U herstart. En dan komt fout nummer drie.

Fout 3: De onzichtbare OOM-kill

Een enkel Chromium-tabblad met een paar open pagina’s verbruikt 2 tot 4 GB RAM. Op een 4 GB VPS blijft er bijna niets over voor OpenClaw zelf, het besturingssysteem en eventuele andere draaiende diensten.

Wanneer Linux geen geheugen meer heeft, beëindigt de OOM-killer van de kernel het proces dat het meeste geheugen verbruikt. Dat is Chromium. Het proces sterft. OpenClaw logt een browser-timeout. Geen crashrapport, geen stacktrace, geen indicatie dat geheugen het probleem was.

Er is ook een subtielere versie van dit probleem. Chromium start voor elk tabblad aparte renderer-processen. Als die niet goed worden opgeruimd, hopen ze zich op. Een GitHub issue documenteerde 39 verweesde renderer-processen die 3,8 GB RAM verbruikten op een VPS die ruim voldoende marge had moeten hebben.

U kunt het achteraf controleren met dmesg | grep -i "oom\|killed\|chromium", maar de meeste mensen denken er niet aan om daar te kijken. Ze herstarten OpenClaw, het werkt een paar minuten, en dan gebeurt het weer.

De officiële serverrequirements-pagina adviseert minimaal 4 GB voor een basissetup. Maar dat getal gaat uit van geen browserautomatisering. Met de browser ingeschakeld is 8 GB de realistische ondergrens. Bij Hetzner is dat het verschil tussen een cpx22 ($5/maand) en een cpx42 ($17/maand).

Fout 4: Het ontbrekende gedeelde geheugen van Docker

Als u OpenClaw in Docker draait (gebruikelijk bij VPS-deployments), is er nog een valkuil. De standaard /dev/shm van Docker is 64 MB. Chromium gebruikt gedeeld geheugen voor interproces-communicatie. Als dat opraakt, crashen tabbladen stilletjes of tonen ze lege pagina’s.

De oplossing is één regel in uw docker-compose.yml:

shm_size: '2gb'

Of mount het expliciet:

volumes:
  - /dev/shm:/dev/shm

Dit staat niet in de setupgids van OpenClaw. Het is Docker-specifiek gedrag dat elke applicatie met Chromium treft, maar tenzij u eerder headless browsers in Docker heeft gedeployed, zou u niet weten dat u hiernaar moet zoeken.

Fout 5: Poortbotsingen waar niemand voor waarschuwt

De browser control service van OpenClaw draait op een aparte poort van het gateway. Standaard is het de gateway-poort plus 2. Als uw gateway op 18789 draait, zou de browser control service op 18791 moeten draaien, en de extension relay op 18792.

In Docker is de browser control service onbereikbaar van buiten de container als u alleen poort 18789 blootstelt. Erger nog, het gateway logt “Browser control service ready” zelfs als poort 18791 nooit daadwerkelijk bindt. Issue #17584 traceerde dit naar het gateway dat de verkeerde module importeerde: een die het “ready”-bericht logt zonder de HTTP-server te starten. Het log zegt dat alles in orde is. De poort is dood.

In Kubernetes, als een andere container in dezelfde pod al poort 9222 (de standaard CDP-poort) gebruikt, detecteert de ensurePortAvailable()-functie van OpenClaw de poort als bezet en weigert verbinding, zelfs als de bezetter precies de Chromium-instantie is waarmee OpenClaw zou moeten communiceren.

GitHub issue #10994 documenteert een geval waarin de VPS-setup van de gebruiker correct werkte. Na een paar geautomatiseerde acties blokkeerde de CDP-poort. De enige oplossing was het vinden en beëindigen van verdwaalde Chromium-processen die de poort vasthielden.

Waarom deze fouten zich opstapelen

Elk van deze vijf problemen heeft een bekende oplossing. Maar ze werken op elkaar in. U lost het snap-probleem op en stuit op de headless-standaard. U corrigeert de configuratie en Chromium start. Het draait tien minuten, dan slaat de OOM-killer toe. U voegt swap-ruimte toe, en nu veroorzaakt de gedeeld-geheugenlimiet van Docker stille renderingfouten. U lost dat op en ontdekt dat poort 18791 niet is blootgesteld.

De debugcyclus ziet er zo uit: fout zoeken, gedeeltelijke oplossing vinden, oplossing toepassen, volgende fout tegenkomen, herhalen. Een Discord-gebruiker beschreef zijn hele besturingssysteem “voor de 3e of 4e keer” opnieuw te hebben geïnstalleerd. Een ander meldde dat de browser “instabiel” was na wat hij dacht dat een complete setup was. Een derde opende een issue met simpelweg de titel “Browser tool consistently fails on VPS.”

Het probleem is niet dat elke individuele oplossing moeilijk is. Het probleem is dat er vijf zijn, ze afhangen van uw specifieke besturingssysteem, pakketbeheerder, container-runtime en VPS-provider, en een enkele fout in de keten betekent dat de browser niet werkt.

Het OpenClaw-team verdient lof voor het gestaag oplossen van gerelateerde bugs. Het misleidende “ready”-log, het opruimen van verweesde renderers en de CDP-poortafhandeling zijn allemaal verbeterd in recente versies. Maar de upstream-fixes behandelen symptomen binnen OpenClaws code. Ze kunnen niet het juiste Chromium-binary op uw server installeren, uw Docker gedeeld geheugen configureren of voldoende RAM toewijzen voor browserautomatisering. Dat blijft uw verantwoordelijkheid.

Hoe we Chromium drie keer hebben laten crashen (en wat we ervan leerden)

We draaien elke OpenClaw.rocks-agent op Kubernetes met onze open-source operator. De browser-sidecar kostte ons weken om goed werkend te krijgen. We liepen tegen onze eigen versie van elk hierboven beschreven probleem aan, plus een paar die alleen optreden in een container-orchestratie-context.

Het idee was simpel: Chromium draaien als een aparte container naast OpenClaw, verbonden via CDP. Eén regel in de Custom Resource en de browser werkt gewoon.

spec:
  chromium:
    enabled: true

Zo is die ene regel daadwerkelijk tot stand gekomen.

Crash 1: Verkeerde gebruiker, alleen-lezen bestandssysteem

Onze eerste poging draaide de Chromium-container als UID 1001 met een alleen-lezen root-bestandssysteem. Beveiligingsbest practice. En volledig kapot. Het browserless-image verwacht UID 999 (blessuser), en Node.js roept bij het starten os.userInfo() aan, wat faalt met ENOENT wanneer de UID geen /etc/passwd-entry heeft. Zelfs na het corrigeren van de UID blokkeerde het alleen-lezen bestandssysteem Chrome bij het schrijven van tijdelijke bestanden. De sidecar crashte bij elke start voordat er een enkele logregel werd geschreven. Issue #12 bevat het volledige verhaal.

Crash 2: De WebSocket-beveiligingsmuur

Met de container eindelijk draaiend was Chromium actief, CDP reageerde op poort 9222, maar OpenClaw weigerde het te gebruiken. Het gateway bond zich aan het LAN-IP van de pod (vereist voor Kubernetes Service-routing), en de beveiligingslaag van OpenClaw blokkeerde plaintext ws://-verbindingen naar niet-loopback-adressen: “SECURITY ERROR: Gateway URL uses plaintext ws:// to a non-loopback address. Both credentials and chat data would be exposed to network interception.”

Een legitieme beveiligingscontrole. Maar in een Kubernetes-pod delen alle containers een netwerknamespace. Verkeer tussen hen verlaat nooit de node. We konden de beveiligingscontrole van OpenClaw niet wijzigen, dus voegden we een nginx reverse proxy sidecar toe die op alle interfaces luistert en doorstuurt naar het gateway op loopback. Het gateway blijft veilig. De Service blijft bereikbaar. Issue #135 documenteert de debugging.

Crash 3: Poort 3000-botsing

Chromium draaide. Het gateway was geproxied. Maar de browser maakte nog steeds geen verbinding. Het browserless-image gebruikt standaard poort 3000, die botste met de interne browser control service van OpenClaw. En toen we overschakelden naar poort 9222, detecteerde OpenClaws ensurePortAvailable() het als “in gebruik door iets anders” en weigerde de verbinding, omdat in een gedeelde netwerknamespace de poort van de sidecar er lokaal uitziet.

De oplossing was het gebruiken van het IP-adres van de pod (via de Kubernetes Downward API) in plaats van localhost voor de CDP-URL. Een niet-loopback-adres vertelt OpenClaw om de remote/attach-only-modus te gebruiken: verbinding maken met wat al draait in plaats van een eigen browser te proberen te starten. PR #183 loste dit op.

Het resultaat: vijf fixes, automatisch toegepast

Elk van deze crashes leerde ons iets. De huidige operator codeert al die kennis:

Sidecar-isolatie. Chromium draait in zijn eigen container. Geen snap. Geen Playwright. Geen headless-flags. Het browserless-image regelt dat allemaal.

Toegewezen resources. De sidecar krijgt eigen CPU- en geheugenlimieten (250m-1000m CPU, 512Mi-2Gi RAM standaard, configureerbaar). Als Chromium zijn geheugenlimiet overschrijdt, herstart Kubernetes alleen de browsercontainer. Uw agent blijft draaien.

Gedeeld geheugen. De operator mount automatisch een op geheugen gebaseerd volume van 1 GB op /dev/shm. Geen Docker shm_size-configuratie nodig.

Poort-routing. Pod-IP voor de CDP-URL activeert de remote-modus. OpenClaw verbindt met de sidecar in plaats van de poort zelf te claimen. Het ensurePortAvailable()-conflict verdwijnt.

Ingebouwde anti-botdetectie. Veel websites detecteren standaard headless Chromium en blokkeren automatisering. De operator ondersteunt extraArgs op de Chromium-sidecar, zodat u flags kunt meegeven zoals --disable-blink-features=AutomationControlled en aangepaste user agents zonder een aangepast containerimage te bouwen:

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"

Beveiliging zonder compromissen. Alle Linux-capabilities verwijderd, privilege-escalatie uitgeschakeld, seccomp RuntimeDefault, non-root UID 999. Geen --no-sandbox als root.

Wat dit voor u betekent

Als u OpenClaw op een VPS draait en de browser werkt, gefeliciteerd. U heeft vijf verschillende faalwijzen doorstaan en bent er aan de andere kant uitgekomen. Houd uw setup. Maak een back-up van uw configuratie.

Als de browser niet werkt, of sporadisch werkt, of als u het zat bent om Chromium te debuggen op een VPS van 5 dollar, bedenk dan wat uw tijd waard is.

OpenClaw.rocks draait elke agent op Kubernetes met de hierboven beschreven operator. De browser-sidecar is vooraf geconfigureerd. Geheugen is toegewezen. Poorten zijn gerouteerd. Beveiliging is versterkt. U installeert niets, configureert niets en debugt niets.

Uw agent krijgt een browser die werkt. Elke keer. Direct uit de doos.

De vijf fixes samengevat

Als u zelf wilt blijven hosten, hier is de volledige checklist:

  1. Vervang snap Chromium door het .deb-pakket van Google Chrome of het standalone binary van Playwright
  2. Schakel headless-modus in: openclaw config set browser.headless true en browser.noSandbox true
  3. Wijs 8 GB+ RAM toe of voeg 4 GB swap toe voor browserautomatisering
  4. Mount gedeeld geheugen in Docker: shm_size: '2gb'
  5. Stel alle drie de poorten bloot: gateway, browser control (gateway + 2) en extension relay (gateway + 3)

Of sla de checklist over. Haal uw assistent op OpenClaw.rocks en laat ons de infrastructuur regelen.