Hospede colegas de IA do OpenBot em um VPS
Veja como hospedar o OpenBot com um container e navegador Chromium por bot, como o gateway autoriza ações e quanta RAM essa arquitetura exige.
O que você obtém ao alojar os colegas de trabalho de IA do OpenBot
Para alojar os colegas de trabalho de IA do OpenBot, execute um servidor gateway e um contentor por bot no hardware que controla. Cada contentor de bot inclui o seu próprio navegador Chromium e o seu próprio volume de workspace, com um perfil do navegador que persiste entre sessões. Todas as ações que um bot executa num computador, ficheiro, servidor MCP (model context protocol) ou componente de UI passam por esse gateway. O gateway verifica cada ação de acordo com uma política antes de a executar e regista-a depois.
O OpenBot é publicado pela CopilotKit ao abrigo da licença MIT em github.com/CopilotKit/openbot. A primeira versão marcada, v0.0.1, foi publicada em 17 August 2026, e o projeto descreve-se como alpha e em desenvolvimento ativo. Trate-o como um projeto com uma arquitetura séria, mas ainda com limitações próprias de uma fase inicial.
A parte interessante dessa arquitetura também é a mais dispendiosa. Um navegador por agente é o custo de memória que muitas pessoas se esquecem de planear. Por isso, o dimensionamento vem antes da instalação neste guia.
Como o gateway decide cada ação
O servidor de API na porta 3001 é o único caminho até ao computador de um bot. Antes de executar uma ação do navegador, o gateway resolve o destino a partir de um instantâneo da página, avalia as regras de política CEL (common expression language) com base no contexto, grava uma linha de auditoria com a decisão e só depois chama o contentor. Se a execução falhar depois disso, grava uma segunda linha. A documentação declara claramente este limite: o computador não decide a política; o gateway do servidor é o limite de execução das ações.
A política usa negação por predefinição, e as regras de negação são avaliadas antes das regras de permissão. A direção da falha é mais importante do que a sintaxe da regra. Uma política em falta não permite nada, e uma regra inválida falha no sentido do bloqueio, seja uma regra de negação ou de permissão. Por isso, um erro na política deixa o bot bloqueado, em vez de deixar o bot com acesso livre às suas contas.
O registo de auditoria fica no PostgreSQL, por isso sobrevive a um reinício. As transferências de controlo são registadas como computer.help_requested, computer.control_taken e computer.control_released. É assim que pode ver um bot pedir intervenção humana e como pode ver a pessoa devolver o controlo. Os segredos são registados como contagens de caracteres, nunca como valores. As operações de ficheiros registam o caminho e o tamanho, nunca o conteúdo. Se quiser o mesmo limite de controlo sem um navegador por trás, colocar as ações de agentes de IA atrás de aprovações aborda esse caso mais restrito.
Quanto custa um bot em RAM e disco
O projeto publica valores medidos para um único Bot em arm64. Estes são os únicos números de dimensionamento publicados pelo OpenBot. Descrevem um bot numa arquitetura, por isso devem ser usados como ponto de partida e não como um plano de capacidade.
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
}
]O pico de memória medido foi de 0.55 GB para um Bot. O mínimo documentado é 2 GB e a recomendação é 4 GB. A diferença entre a medição e o mínimo deixa margem para o Chromium crescer sob carga, porque o consumo de memória de um navegador acompanha as páginas abertas e não o processo em repouso. O consumo de CPU em idle é quase nulo, com 0.06 de um core no topo do intervalo medido. Portanto, não é CPU que está a dimensionar. É disco. A imagem sozinha ocupa 5.3 GB, face ao volume recomendado de 10 GB. Ela é tão grande porque inclui os binários Firefox e WebKit do Playwright, além do Chromium.
Nada disso indica quanto custam vários bots em conjunto, e o projeto não publica nenhum valor para esse caso. Faça a sua própria medição. Inicie um bot, atribua-lhe uma tarefa real com uma página aberta e monitorize o contentor enquanto trabalha.
docker stats --no-stream
free -mUse a coluna MEM USAGE do contentor do bot como valor por bot. Some o gateway e o PostgreSQL. Depois multiplique o valor por bot pelo número de bots que espera ter em execução ao mesmo tempo. Um bot idle continua a manter um processo do navegador, por isso o multiplicador aplica-se aos bots existentes e não apenas aos bots ocupados. O cálculo é o mesmo usado para dimensionar RAM e CPU para uma VPS com um agente de programação. A parte relativa ao navegador é explicada em executar um navegador headless para agentes numa VPS.
Um detalhe do Chromium afeta os planos pequenos. O OpenBot inicia o Chromium com --disable-dev-shm-usage, por isso o navegador grava em /tmp em vez de /dev/shm. Isto evita o crash que ocorre em hosts com um /dev/shm pequeno e transfere a pressão para o sistema de ficheiros raiz. Esse é mais um motivo para o disco recomendado ser maior do que a imagem.
Como alojar o OpenBot num VPS?
Precisa de Docker, Bun 1.3 ou posterior, um projeto CopilotKit Intelligence e uma chave de API do modelo. A documentação de desenvolvimento também espera lsof, python3 e curl no servidor. Clone uma release identificada por uma tag em vez de main, porque main num projeto alfa muda sem aviso.
git clone --branch v0.0.1 https://github.com/CopilotKit/openbot.git
cd openbot
cp .env.example .envProvisione o projeto Intelligence. Estes três comandos gravam a chave de runtime e o token de licença no ficheiro de ambiente.
npx --yes copilotkit@latest login
npx --yes copilotkit@latest project select
npx --yes copilotkit@latest license --writeGere a chave que cifra as credenciais armazenadas e coloque o resultado em .env como KEY_ENCRYPTION_KEY. Adicione o seu OPENAI_API_KEY ao mesmo ficheiro ou defina BOT_PROVIDER como anthropic ou google com a chave correspondente.
openssl rand -base64 32Depois, instale e inicie os serviços.
bun install
bash scripts/start.shscripts/start.sh inicia os serviços Docker, executa as migrações da base de dados, inicia o servidor e a aplicação e verifica o estado de saúde de ambos. Quando termina, a aplicação responde na porta 3010 e a API na porta 3001. O script comunica conflitos de portas e deixa inalterado um serviço correspondente que já esteja em execução, por isso é seguro executá-lo duas vezes.
Verifique o serviço no próprio servidor antes de expor qualquer porta.
curl -sS -o /dev/null -w '%{http_code}\n' http://127.0.0.1:3010
ss -ltnp | grep -E ':(3010|3001|4100|4500|5432)'Um 200 do primeiro comando significa que a aplicação está a responder. O segundo comando mostra a que endereços essas portas estão associadas, e essa é a informação relevante num VPS. Uma linha com 127.0.0.1:3001 indica que a porta está acessível apenas no servidor. Uma linha com 0.0.0.0:3001 significa que qualquer pessoa com uma rota até ao servidor pode aceder-lhe.
A imagem de contentor única
A documentação de implementação também fornece uma única imagem que inclui a aplicação, a API e o Chromium, servida na porta 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 openbotEMBEDDED_POSTGRES=on executa o PostgreSQL dentro do contentor e aplica as migrações no arranque. O volume nomeado preserva o histórico de auditoria entre implementações. Sem esse volume, cada reconstrução elimina esse histórico. Se apontar DATABASE_URL para uma base de dados gerida, a extensão vector tem de estar ativada nessa base de dados. Serviços geridos como RDS, Cloud SQL e Azure Database suportam a extensão, mas nenhum deles a ativa automaticamente. Por isso, uma migração contra uma base de dados gerida nova falha porque o tipo de coluna vector ainda não existe.
Execute as migrações como uma etapa da versão quando a base de dados for externa.
docker run --rm --env-file .env openbot \
sh -c "cd /app/server && bun x drizzle-kit migrate --config=drizzle.config.ts"Essa imagem deixa deliberadamente a porta do navegador sem publicação. Também não inclui o supervisor, porque o supervisor precisa do socket do Docker, que as plataformas serverless não disponibilizam. Sem o supervisor, todos os bots partilham um navegador e, portanto, o mesmo conjunto de credenciais. Isso elimina o isolamento que justificava executar contentores separados por bot. Se a razão para estar a utilizar este sistema for ter credenciais separadas por bot, execute a stack do compose com COMPUTER_SUPERVISOR_URL e SUPERVISOR_TOKEN definidos, num host onde aceite esse compromisso. Um processo que consiga comunicar com o socket do Docker pode iniciar um contentor privilegiado. Na prática, esse processo tem acesso root ao host. Essa é uma boa razão para manter o OpenBot numa máquina própria, seguindo o mesmo princípio de dar aos agentes de programação uma VM descartável.
Por que OPENBOT_SINGLE_USER é uma configuração para portáteis
.env.example é lançado com OPENBOT_SINGLE_USER=true. Essa configuração aceita todos os pedidos como se viessem de um único administrador e ignora completamente o início de sessão. Num portátil, é conveniente, porque o único cliente que consegue aceder à porta é você. Num VPS, isso significa que a primeira pessoa que aceder à porta 3010 se torna administradora de um sistema que armazena credenciais encriptadas e controla um navegador já autenticado nas suas contas.
Há duas formas seguras de executar a aplicação. Mantenha OPENBOT_SINGLE_USER=true, associe todas as portas a 127.0.0.1 e aceda à aplicação apenas através de um túnel SSH ou de uma interface de rede privada.
ssh -N -L 3010:127.0.0.1:3010 -L 3001:127.0.0.1:3001 you@your-vpsA aplicação fica então disponível em http://localhost:3010 no seu próprio navegador. Isso conta como um contexto seguro, pelo que os cookies de início de sessão e as funcionalidades do navegador de que o ecrã interativo precisa funcionam corretamente. A outra opção é desativar o modo de utilizador único e configurar um fornecedor de identidade real. Google, Microsoft Entra, Okta, SAML e OIDC são suportados. Qualquer fornecedor também precisa de BETTER_AUTH_SECRET com 32 caracteres ou mais, de BETTER_AUTH_URL definido como o URL base público da API para os callbacks OAuth, de INITIAL_ADMIN_EMAILS e de TRUSTED_ORIGINS. As credenciais do fornecedor têm de estar completas, porque um fornecedor configurado apenas parcialmente impede o arranque em vez de voltar ao acesso aberto.
Se a aplicação estiver acessível através de um nome público, coloque TLS (transport layer security) à frente dela. Uma página servida por http:// simples, em qualquer endereço que não seja localhost, não é um contexto seguro. Por isso, os cookies marcados com Secure não são armazenados e o início de sessão falha de uma forma que parece ser um erro do OpenBot.
Bloqueie as portas de nível inferior
A própria nota de segurança do OpenBot afirma que os endpoints dos serviços de nível inferior são protegidos por tokens, que deve mantê-los privados e que não deve utilizá-los para contornar o gateway. Os tokens são a segunda proteção. A primeira é impedir completamente o acesso à porta.
O agent-computer escuta na porta 4100 e exige COMPUTER_TOKEN. Os endpoints do bot escutam nas portas 4200 e 4201. O supervisor escuta na porta 4500 no host e na porta 4300 dentro do respetivo contentor. O PostgreSQL escuta na porta 5432. Nenhuma dessas portas deve estar numa interface pública. Numa implementação para um único utilizador, o mesmo se aplica à aplicação e à API.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw enable
sudo ufw status verboseExiste uma armadilha que afeta quem presume que o firewall é suficiente. Publicar uma porta de contentor com -p 3001:3001 faz com que o Docker instale uma regra DNAT. Assim, o tráfego é tratado no caminho FORWARD e nunca passa pela cadeia INPUT, que é abrangida pela política de negação predefinida do ufw. A porta continua aberta, embora ufw status ainda apresente Status: active. Vincule a porta publicada ao loopback diretamente no mapeamento, como em -p 127.0.0.1:3001:3001, ou defina o endereço do host no seu ficheiro compose. Verifique com ss -ltnp, não com ufw status.
O OpenBot não é uma stack offline
Tenha isto em conta antes de planear a implementação. O OpenBot depende de um projeto CopilotKit Intelligence, que mantém threads persistentes e a memória das conversas fora do seu servidor. O servidor valida INTELLIGENCE_API_URL, INTELLIGENCE_GATEWAY_WS_URL, INTELLIGENCE_API_KEY e COPILOTKIT_LICENSE_TOKEN no arranque, e os quatro têm de estar presentes em conjunto; caso contrário, o arranque falha. Está disponível um plano gratuito desde August 2026, e o próprio Intelligence pode ser alojado localmente. Por isso, é possível fazer uma implementação totalmente local, mas com mais trabalho do que o quickstart mostra.
O modelo é a segunda dependência externa. Nada é fornecido localmente. BOT_PROVIDER aceita openai, anthropic ou google, e OPENAI_BASE_URL encaminha o percurso OpenAI para qualquer endpoint compatível. É aqui que se enquadra executar o Ollama numa VPS para alojar localmente um LLM, se quiser manter os tokens no seu próprio hardware. O controlo do browser exige bastante do modelo. Teste um modelo local numa tarefa real antes de o escolher.
Execute uma réplica por enquanto
O gateway armazena instantâneos de páginas na memória do processo do servidor. Com duas réplicas, um instantâneo obtido por um processo fica invisível para o outro. Por isso, as ações falham de forma intermitente com erros de elemento não encontrado, que parecem aleatórios. A documentação de implementação é explícita: execute uma única réplica e defina o número máximo de instâncias da sua plataforma como 1. Esse limite deixa de ser necessário quando o armazenamento em cache dos instantâneos passar para a base de dados. Até lá, aumente a capacidade do OpenBot usando uma máquina maior, e não adicionando máquinas. O isolamento entre bots continua a ser fornecido pelos contentores de cada bot, da mesma forma que sandboxes de agentes autoalojados impedem que os erros de um agente afetem os restantes.
Modos de falha e o que verá
O arranque termina imediatamente depois de preencher .env. O servidor valida a configuração antes de disponibilizar qualquer serviço. Um bloco Intelligence incompleto, KEY_ENCRYPTION_KEY em falta ou um fornecedor OAuth com um ID de cliente sem segredo fazem o arranque falhar, em vez de degradarem silenciosamente. Leia o primeiro erro, corrija esse campo e tente iniciar novamente.
As migrações falham numa base de dados gerida. A extensão vector não está ativada por predefinição, por isso a migração encontra um tipo de coluna que o PostgreSQL não conhece. Ligue-se como superuser, execute CREATE EXTENSION vector; e repita o passo de migração.
A aplicação carrega, mas o início de sessão nunca fica ativo. Está a servir através de http:// sem encriptação num endereço público. Esse contexto não é seguro, por isso o cookie Secure é descartado. Coloque TLS à frente da aplicação ou use o túnel SSH para que o browser veja localhost.
Os bots partilham inícios de sessão que esperava que fossem separados. O supervisor não está em execução. Por isso, não existe um computador por bot e todos os bots usam o browser partilhado. Confirme que COMPUTER_SUPERVISOR_URL está definido e que o supervisor consegue aceder ao socket do Docker.
Um bot para e pede ajuda. Esse é o comportamento previsto. O registo de auditoria grava computer.help_requested, assume o controlo no ecrã ativo e a transferência fica registada de ambos os lados.
FAQ
O que significa deixar OPENBOT_SINGLE_USER ativado numa implementação VPS?
Só é seguro quando o gateway não pode ser alcançado a partir da Internet. OPENBOT_SINGLE_USER=true aceita todos os pedidos como um único administrador, sem início de sessão. Qualquer pessoa que consiga abrir a porta controla a implementação, as credenciais armazenadas e o browser com sessão iniciada. Isto é aceitável quando todas as portas estão associadas a 127.0.0.1 e a aplicação é acedida através de um túnel SSH ou de uma interface de rede privada. Numa interface pública, desative-o e configure Google, Microsoft Entra, Okta ou OIDC em conjunto com BETTER_AUTH_SECRET, BETTER_AUTH_URL, INITIAL_ADMIN_EMAILS e TRUSTED_ORIGINS.
De quanta RAM precisa um bot OpenBot?
Os valores publicados pelo projeto para um único Bot em arm64 indicam um pico de memória de 0.55 GB, com 2 GB como mínimo documentado e 4 GB recomendados. Não existe um valor publicado para vários bots em simultâneo, porque cada um mantém o seu próprio Chromium. Execute um bot numa tarefa real, consulte a memória desse container em docker stats, adicione o gateway e a base de dados e multiplique pelo número de bots que espera ter em execução ao mesmo tempo.
Preciso de uma conta CopilotKit para alojar o OpenBot por minha conta?
Sim. O OpenBot depende de um projeto CopilotKit Intelligence para manter threads e memória de forma persistente. O servidor recusa iniciar enquanto não estiverem definidos o URL da API Intelligence, o URL WebSocket do gateway, a chave da API e o token de licença. Existe um plano gratuito desde agosto de 2026, e o Intelligence pode ser alojado por si. Assim, a dependência do serviço alojado pode ser removida com trabalho adicional. Também tem de fornecer a sua própria chave da API do modelo, porque o OpenBot não inclui nenhum modelo.
Porque é que cada bot recebe o seu próprio browser em vez de partilhar um?
Porque um perfil de browser é uma identidade. Um browser partilhado significa cookies e sessões partilhados. Assim, se um bot iniciar sessão numa conta, todos os bots ficam com sessão iniciada nessa conta. Os containers separados por bot dão a cada colaborador o seu próprio perfil e as suas próprias sessões. O custo é a memória, porque um Chromium por bot é o maior item individual do dimensionamento.
Que portas do OpenBot devem estar abertas na firewall?
Nenhuma das portas de nível inferior. O agent-computer na porta 4100, os endpoints dos bots nas portas 4200 e 4201, o supervisor na porta 4500 e o PostgreSQL na porta 5432 devem permanecer privados. O projeto protege-os com tokens e recomenda que continue a impedir o seu acesso. Publique apenas o que uma pessoa precisa de abrir. Tenha também em atenção que uma porta de container publicada com -p 3001:3001 pode ser alcançada independentemente de uma regra ufw default-deny, porque a regra DNAT do Docker coloca esse tráfego no caminho FORWARD, em vez de INPUT.