SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-28

OpenBot AI-collega's zelf hosten op een VPS

Host OpenBot AI-collega's in eigen containers met een toegewezen Chromium-browser. Ontdek hoe de gateway acties valideert en wat het RAM-verbruik is per actieve bot-instantie.

Wat u krijgt bij het zelf hosten van OpenBot AI-collega's

U host OpenBot AI-collega's zelf door één gateway-server en één container per bot uit te voeren op hardware die u beheert. Elke bot-container bevat een eigen Chromium-browser en een eigen workspace-volume, met een browserprofiel dat tussen sessies behouden blijft. Elke actie die een bot uitvoert op een computer, een bestand, een MCP-server (model context protocol) of een UI-component verloopt via die gateway. De gateway toetst de actie aan een beleid voordat deze wordt uitgevoerd en legt deze daarna vast. Als de agent-loop die de gateway omhult nog onbekend terrein voor u is, kunt u via het stappenplan in AI-agents vanaf nul leren eerst zelf een kleine agent schrijven voordat u een bot toegang geeft tot een browser en uw inloggegevens.

OpenBot wordt uitgebracht door CopilotKit onder de MIT-licentie op github.com/CopilotKit/openbot. De eerste getagde release, v0.0.1, werd gepubliceerd op 17 augustus 2026 en het project omschrijft zichzelf als alpha en in actieve ontwikkeling. Beschouw het als een serieus ontwerp met nog enkele scherpe randjes.

Het interessante deel van die architectuur is tevens het kostbare deel. Een browser voor elke agent is de geheugenkost waar de meeste mensen geen rekening mee houden bij hun planning, dus het bepalen van de benodigde capaciteit gaat hier vooraf aan de installatie.

Hoe de gateway elke actie bepaalt

De API-server op poort 3001 is het enige pad naar de computer van een bot. Voordat een browseractie wordt uitgevoerd, bepaalt de gateway het doel op basis van een paginasnapshot, evalueert deze CEL (common expression language) beleidsregels aan de hand van de context, schrijft een audit-regel met de beslissing en roept pas daarna de container aan. Als de uitvoering daarna mislukt, schrijft deze een tweede regel. De documentatie stelt de grens duidelijk: de computer bepaalt het beleid niet, de server-gateway is de actiegrens. Die splitsing heeft buiten OpenBot een naam, omdat de loop, de tooldefinities, de toegangscontroles en de sessiestatus samen het harnas rondom een model vormen, en deze gateway is de autorisatiehelft daarvan.

Het beleid is standaard 'deny-by-default' en 'deny'-regels worden geëvalueerd vóór 'allow'-regels. De richting van de fout is belangrijker dan de syntaxis van de regel. Een ontbrekend beleid staat niets toe, en een defecte regel blokkeert bij een fout, ongeacht of het een 'deny'- of 'allow'-regel betreft. Een fout in uw beleid leidt dus tot een vastgelopen bot in plaats van een bot die ongecontroleerd toegang heeft tot uw accounts. Die laag regelt wat een bot doet en niet wat deze leest. Een pagina met instructies voor de agent blijft daarom een afzonderlijk probleem; dit is hetzelfde 'prompt injection'-oppervlak waar u mee te maken krijgt wanneer u een agent resultaten van uw eigen SearXNG-instantie geeft.

Het audit-spoor bevindt zich in PostgreSQL, waardoor het een herstart overleeft. Overdrachten van controle worden geregistreerd als computer.help_requested, computer.control_taken en computer.control_released; zo ziet u wanneer een bot om een mens vraagt en hoe de mens de controle teruggeeft. Geheimen worden geregistreerd als aantal tekens, nooit als waarden. Bestandsbewerkingen registreren het pad en de grootte, nooit de inhoud. Als u dezelfde controlegrens wilt zonder een browser erachter, behandelt het beveiligen van AI-agentacties met goedkeuringen dat specifiekere scenario.

Wat één bot kost aan RAM en schijfruimte

Het project publiceert gemeten cijfers voor één enkele Bot op arm64. Dit zijn de enige dimensiecijfers die OpenBot vrijgeeft. Ze beschrijven één bot op één architectuur; beschouw ze daarom als uitgangspunt en niet als een capaciteitsplan.

ChartOpenBot published resource figures, one Bot on arm64 (August 2026)
The data behind this chart
[
  {
    "label": "Measured, one Bot",
    "memory_gb": 0.55,
    "disk_gb": 5.3,
    "vcpu": 0.06
  },
  {
    "label": "Documented minimum",
    "memory_gb": 2,
    "disk_gb": 8,
    "vcpu": 1
  },
  {
    "label": "Documented recommended",
    "memory_gb": 4,
    "disk_gb": 10,
    "vcpu": 2
  }
]

Het piekgeheugengebruik werd gemeten op 0.55 GB voor één Bot, terwijl het gedocumenteerde minimum 2 GB is en de aanbeveling 4 GB bedraagt. Het verschil tussen de meting en het minimum is de ruimte die Chromium nodig heeft om onder belasting te groeien, omdat het geheugengebruik van een browser afhangt van de geopende pagina's en niet van het proces in ruststand. Het CPU-gebruik in ruststand is verwaarloosbaar, op 0.06 van een core aan de bovengrens van het gemeten bereik; u koopt dus geen CPU-capaciteit. U koopt schijfruimte. De image alleen al is 5.3 GB, tegenover een aanbevolen volume van 10 GB. Deze omvang komt doordat de image naast Chromium ook de Firefox- en WebKit-binaries van Playwright bevat.

Niets hiervan vertelt u wat meerdere bots samen kosten, en het project publiceert hier geen cijfers over. Een gedocumenteerd minimum is een getal dat een project durft te publiceren, in plaats van een waarde die onder belasting is geobserveerd. Dit is ook de reden waarom kiezen tussen PhotoPrism en Immich neerkomt op hun gemeten RAM-ondergrenzen in plaats van de gepubliceerde waarden. Meet het zelf. Start één bot, geef deze een echte taak met een geopende pagina en monitor de container terwijl deze werkt.

docker stats --no-stream
free -m

Gebruik de MEM USAGE-kolom voor de container van de bot als uw cijfer per bot, tel daar de gateway en PostgreSQL bij op en vermenigvuldig het cijfer per bot met het aantal bots dat u gelijktijdig wilt draaien. Een inactieve bot houdt nog steeds een browserproces vast, dus de vermenigvuldiger is van toepassing op alle bestaande bots, niet alleen op de actieve. De berekening is dezelfde als die voor het dimensioneren van RAM en CPU voor een coding agent VPS, en het browseraspect hiervan wordt behandeld in het draaien van een headless browser voor agents op een VPS.

Eén detail over Chromium is van invloed op kleine abonnementen. OpenBot start Chromium met --disable-dev-shm-usage, waardoor de browser schrijft naar /tmp in plaats van /dev/shm. Dit voorkomt crashes op hosts met een kleine /dev/shm en verplaatst de druk naar uw root-bestandssysteem. Dit is een extra reden waarom de aanbevolen schijfruimte groter is dan de image zelf.

Hoe host u OpenBot zelf op een VPS?

U heeft Docker, Bun 1.3 of nieuwer, een CopilotKit Intelligence-project en een model-API-key nodig. De ontwikkelingsdocumentatie vereist ook lsof, python3 en curl op de server. Kloon een getagde release in plaats van main, omdat main bij een alfaproject zonder waarschuwing wijzigt.

git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .env

Provisioneer het Intelligence-project. Deze drie commando's schrijven de runtime-key en het licentietoken naar uw omgevingsbestand.

npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --write

Genereer de key die opgeslagen inloggegevens versleutelt en plaats de uitvoer in .env als KEY_ENCRYPTION_KEY. Voeg uw OPENAI_API_KEY toe in hetzelfde bestand, of stel BOT_PROVIDER in op anthropic of google met de bijbehorende key.

openssl rand -base64 32

Installeer en start vervolgens de applicatie.

bun install
bash scripts/start.sh

scripts/start.sh start de Docker-services, voert de databasemigraties uit, start de server en de app, en controleert de status. Wanneer dit proces is voltooid, reageert de app op poort 3010 en de API op poort 3001. Het script rapporteert poortconflicten en laat een reeds draaiende, overeenkomstige service ongemoeid; het script twee keer uitvoeren is dus veilig.

Controleer de werking vanaf de server zelf voordat u services blootstelt aan het internet.

curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3010
ss -ltnp | grep -E ':(3010|3001|4100|4500|5432)'

Een 200 bij het eerste commando betekent dat de app actief is. Het tweede commando toont aan welke adressen deze poorten zijn gebonden, en dat is het antwoord dat ertoe doet op een VPS. Een regel met 127.0.0.1:3001 is privé voor de server. Een regel met 0.0.0.0:3001 betekent dat iedereen die een route naar de server heeft, de service kan bereiken.

De container-image voor alles-in-één

De documentatie voor de deployment levert ook een enkele image die de app, de API en Chromium bevat, welke wordt aangeboden op poort 3001.

docker build -t openbot .
docker run -p 127.0.0.1:3001:3001 --env-file .env \
  -e EMBEDDED_POSTGRES=on -v openbot-data:/var/lib/postgresql/data openbot

EMBEDDED_POSTGRES=on draait PostgreSQL binnen de container en voert migraties uit bij het opstarten. De named volume behoudt de audit-geschiedenis bij een redeploy; zonder deze volume gaat die geschiedenis bij elke rebuild verloren. Als u DATABASE_URL in plaats daarvan naar een managed database laat wijzen, moet de vector extensie daarop zijn ingeschakeld. Managed services zoals RDS, Cloud SQL en Azure Database ondersteunen deze extensie, maar geen van deze diensten schakelt deze automatisch voor u in. Hierdoor mislukt een migratie op een nieuwe managed database omdat het kolomtype vector nog niet bestaat.

Voer migraties uit als een release-stap wanneer de database extern is.

docker run --rm --env-file .env openbot \
  sh -c "cd /app/server && bun x drizzle-kit migrate --config=drizzle.config.ts"

Die image laat de browserpoort bewust ongepubliceerd. Ook de supervisor is weggelaten, omdat de supervisor toegang nodig heeft tot de Docker socket, wat serverless-platformen niet bieden. Zonder de supervisor deelt elke bot één browser en daarmee één set inloggegevens. Dit heft de isolatie op die het draaien van containers per bot juist waardevol maakt. Als u hier bent vanwege de behoefte aan aparte inloggegevens per bot, draai dan de compose-stack met COMPUTER_SUPERVISOR_URL en SUPERVISOR_TOKEN ingesteld op een host waar u dit compromis accepteert. Een proces dat kan communiceren met de Docker socket kan in de praktijk een geprivilegieerde container starten en is daarmee in feite root op de host. Dat is een goede reden om OpenBot op een eigen machine te draaien, in de geest van coding agents een wegwerp-VM geven.

Waarom OPENBOT_SINGLE_USER een instelling voor laptops is

.env.example wordt geleverd met OPENBOT_SINGLE_USER=true. Deze instelling accepteert elk verzoek als één beheerder en slaat het inloggen volledig over. Op een laptop is dit handig, omdat u de enige client bent die de poort kan bereiken. Op een VPS betekent dit dat de eerste persoon die poort 3010 bereikt, beheerder wordt van een systeem dat versleutelde inloggegevens opslaat en een browser aanstuurt die al is ingelogd op uw accounts.

Er zijn twee correcte manieren om dit uit te voeren. Behoud OPENBOT_SINGLE_USER=true, bind elke poort aan 127.0.0.1 en benader de applicatie uitsluitend via een SSH-tunnel of een privé-netwerkinterface.

ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vps

De applicatie is dan beschikbaar op http://localhost:3010 in uw eigen browser, wat geldt als een veilige context. Hierdoor werken inlogcookies en de browserfuncties die het live-scherm nodig heeft naar behoren. De andere manier is om de single-user modus uit te schakelen en een echte identiteitsprovider te configureren. Google, Microsoft Entra, Okta, SAML en OIDC worden ondersteund. Elke provider vereist ook BETTER_AUTH_SECRET van 32 tekens of meer, BETTER_AUTH_URL ingesteld op de publieke API-basis-URL voor OAuth-callbacks, INITIAL_ADMIN_EMAILS en TRUSTED_ORIGINS. De inloggegevens van de provider moeten volledig zijn, omdat een half geconfigureerde provider de opstartprocedure stopt in plaats van terug te vallen op open toegang. Als u accounts toevoegt omdat elk teamlid een eigen agent wil in plaats van een eigen browser, dan is OneCLI vanaf het begin rond dat model ontworpen, met één gesandboxte agent per persoon en de modelsleutels beheerd in een centrale gateway.

Als de applicatie bereikbaar is via een publieke naam, plaats er dan TLS (transport layer security) voor. Een pagina die wordt geserveerd via onversleuteld http:// op iets anders dan localhost is geen veilige context. Hierdoor worden cookies gemarkeerd met Secure niet opgeslagen en mislukt het inloggen op een manier die lijkt op een bug in OpenBot.

Beveilig de poorten op laag niveau

De eigen beveiligingsnotitie van OpenBot stelt dat de service-endpoints op laag niveau worden beschermd door tokens, dat u deze privé moet houden en dat u ze niet moet gebruiken om de gateway te omzeilen. Tokens vormen de tweede beschermingslaag. De eerste laag is dat de poort in het geheel niet bereikbaar is.

De agent-computer luistert op 4100 en vereist COMPUTER_TOKEN. De bot-endpoints luisteren op 4200 en 4201. De supervisor luistert op 4500 op de host en op 4300 binnen de container. PostgreSQL luistert op 5432. Geen van deze hoort op een publieke interface thuis, en bij een implementatie voor één gebruiker geldt dit ook voor de app en de API.

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verbose

Er is hier een valkuil voor mensen die aannemen dat de firewall voldoende is. Het publiceren van een containerpoort met -p 3001:3001 zorgt ervoor dat Docker een DNAT-regel installeert. Hierdoor wordt verkeer afgehandeld in het FORWARD-pad en passeert het nooit de INPUT-chain waar het standaard 'deny'-beleid van ufw over gaat. De poort blijft open terwijl ufw status nog steeds Status: active weergeeft. Koppel de gepubliceerde poort aan de loopback-interface in de mapping zelf, zoals -p 127.0.0.1:3001:3001, of stel het hostadres in uw compose-bestand in. Controleer dit met ss -ltnp, niet met ufw status. Niets aan deze valkuil is specifiek voor OpenBot, dus voer dezelfde controle uit voor elke andere container die u op de server heeft gepubliceerd, inclusief alles wat dient als een Jellyfin-bibliotheek herbouwd als een videotheek uit de jaren 90.

OpenBot is geen offline stack

Houd hier rekening mee voordat u de implementatie plant. OpenBot is afhankelijk van een CopilotKit Intelligence-project, dat duurzame threads en gespreksgeheugen buiten uw eigen server opslaat. De server valideert INTELLIGENCE_API_URL, INTELLIGENCE_GATEWAY_WS_URL, INTELLIGENCE_API_KEY en COPILOTKIT_LICENSE_TOKEN bij het opstarten; alle vier moeten aanwezig zijn, anders mislukt het opstarten. Sinds augustus 2026 is er een gratis abonnement beschikbaar en Intelligence is zelf ook self-hostable, waardoor een volledig lokale implementatie mogelijk is, al vereist dit meer werk dan de quickstart laat zien.

Het model is de tweede externe afhankelijkheid. Niets wordt standaard meegeleverd. BOT_PROVIDER accepteert openai, anthropic of google, en OPENAI_BASE_URL wijst het OpenAI-pad naar elk compatibel eindpunt. Hier komt Ollama draaien op een VPS voor het zelf hosten van een LLM van pas als u wilt dat de tokens op uw eigen hardware blijven. Browserbesturing vraagt veel van een model, dus test een lokaal model met een echte taak voordat u zich hieraan verbindt.

Draai voorlopig één replica

De gateway slaat pagina-snapshots op in het geheugen van het serverproces. Bij twee replica's is een snapshot die door het ene proces is gemaakt onzichtbaar voor het andere, waardoor acties met tussenpozen falen met element-not-found-fouten die willekeurig lijken. De documentatie voor de implementatie is expliciet: draai een enkele replica en zet het maximale aantal instanties van uw platform vast op 1. Die limiet vervalt zodra de snapshot-caching naar de database verhuist. Tot die tijd schaalt u OpenBot door de server krachtiger te maken, niet door meer servers toe te voegen. Isolatie tussen bots wordt nog steeds gewaarborgd door de containers per bot, op dezelfde manier waarop self-hosted agent sandboxes de fouten van de ene agent gescheiden houden van de andere.

Foutmodi en wat u zult zien

De opstartprocedure stopt onmiddellijk nadat u .env heeft ingevuld. De server valideert de configuratie voordat deze services aanbiedt. Een onvolledig Intelligence-blok, een ontbrekende KEY_ENCRYPTION_KEY of een OAuth-provider met een client ID maar zonder secret zorgen er elk voor dat het opstarten stopt in plaats van dat de applicatie in een beperkte modus verdergaat. Lees de eerste foutmelding, corrigeer dat specifieke veld en start opnieuw.

Migraties mislukken op een beheerde database. De vector-extensie is standaard niet ingeschakeld, waardoor de migratie een kolomtype tegenkomt dat PostgreSQL niet herkent. Maak verbinding als superuser, voer CREATE EXTENSION vector; uit en voer daarna de migratiestap opnieuw uit.

De applicatie laadt, maar inloggen blijft niet behouden. U serveert de applicatie via onversleuteld http:// op een publiek adres; dit is geen veilige context, waardoor de Secure-cookie wordt geweigerd. Plaats TLS voor de applicatie of gebruik een SSH-tunnel zodat de browser localhost ziet.

Bots delen inloggegevens waarvan u verwachtte dat ze gescheiden zouden zijn. De supervisor draait niet, waardoor er geen per-bot computeromgeving is en elke bot dezelfde browser gebruikt. Controleer of COMPUTER_SUPERVISOR_URL is ingesteld en of de supervisor toegang heeft tot de Docker-socket.

Een bot stopt en vraagt om hulp. Dit is het beoogde ontwerp. Het audit-logboek legt computer.help_requested vast, u neemt de controle over via het live-scherm en de overdracht wordt aan beide kanten geregistreerd.

FAQ

Is het veilig om OPENBOT_SINGLE_USER ingeschakeld te laten voor een VPS-implementatie?

Alleen wanneer de gateway niet bereikbaar is vanaf het internet. OPENBOT_SINGLE_USER=true accepteert elk verzoek als één beheerder zonder inlogprocedure; iedereen die de poort kan openen, krijgt dus volledige controle over de implementatie, de opgeslagen inloggegevens en de ingelogde browser. Dit is acceptabel wanneer elke poort is gebonden aan 127.0.0.1 en u de applicatie benadert via een SSH-tunnel of een privé-netwerkinterface. Schakel dit op een publieke interface uit en configureer Google, Microsoft Entra, Okta of OIDC in combinatie met BETTER_AUTH_SECRET, BETTER_AUTH_URL, INITIAL_ADMIN_EMAILS en TRUSTED_ORIGINS.

Hoeveel RAM heeft één OpenBot-bot nodig?

De gepubliceerde cijfers van het project voor een enkele bot op arm64 stellen het piekgeheugengebruik op 0.55 GB, met 2 GB als gedocumenteerd minimum en 4 GB als aanbevolen hoeveelheid. Er is geen gepubliceerd cijfer voor meerdere bots tegelijk, omdat elke bot een eigen Chromium-instantie draait. Laat één bot een echte taak uitvoeren, lees het geheugengebruik van die container uit in docker stats, tel de gateway en de database erbij op en vermenigvuldig dit met het aantal bots dat u gelijktijdig verwacht te draaien.

Heb ik een CopilotKit-account nodig om OpenBot zelf te hosten?

Ja. OpenBot is afhankelijk van een CopilotKit Intelligence-project voor duurzame threads en geheugen, en de server weigert te starten tenzij de Intelligence API URL, de gateway WebSocket URL, de API-sleutel en het licentietoken zijn ingesteld. Sinds augustus 2026 is er een gratis abonnement beschikbaar en kan Intelligence zelf worden gehost, waardoor de afhankelijkheid van de gehoste dienst met extra werk kan worden verwijderd. U levert ook uw eigen model-API-sleutel aan, aangezien er geen model wordt meegeleverd met OpenBot.

Waarom krijgt elke bot een eigen browser in plaats van er één te delen?

Omdat een browserprofiel een identiteit is. Een gedeelde browser betekent gedeelde cookies en gedeelde sessies; één bot die is ingelogd op een account betekent dus dat elke bot op dat account is ingelogd. Containers per bot geven elke medewerker een eigen profiel en eigen inloggegevens. De kosten hiervan zijn geheugengebruik, aangezien een Chromium-instantie per bot de grootste factor is in de dimensionering.

Welke OpenBot-poorten moeten openstaan op de firewall?

Geen van de poorten op laag niveau. De agent-computer op 4100, de bot-endpoints op 4200 en 4201, de supervisor op 4500 en PostgreSQL op 5432 blijven allemaal privé. Het project beveiligt deze met tokens en verzoekt u ze sowieso onbereikbaar te houden. Publiceer alleen wat een gebruiker nodig heeft om te openen, en onthoud dat een containerpoort die is gepubliceerd met -p 3001:3001 bereikbaar is, ongeacht een ufw default-deny regel, omdat de DNAT-regel van Docker dat verkeer in het FORWARD-pad plaatst in plaats van INPUT.